dhp-faq - 984k - Fakultät für Informatik

Transcrição

dhp-faq - 984k - Fakultät für Informatik
DHP-FAQ
Datenbanken
Compilerbau
Software Engineering
Objektorientierung
Rechnerarchitektur
Betriebssysteme
Rechnernetze
Rechnernetze II
Effiziente Algorithmen und Datenstrukturen
Automaten, Formale Sprachen, Berechenbarkeit
Logik
http://www.deissenboeck.de/faqs
DHP-FAQ
Wie auch bei den DVP-FAQs sind hier wieder alle, mir relevant erscheinenden, Fragen aus den Protokollen
zusammengefasst. Wieder gilt, dass die Antworten zum grossen Teil direkt aus der angegebenen Literatur
übernommen wurden und daher nicht auf meine geistige Leistung zurück gehen. Trotzdem kann es natürlich
gut sein, dass ein Haufen Fehler drin sind. Viel Spass damit.
Florian Deißenböck, 03.04.2003
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
2
Inhaltsverzeichnis
I
Praktische Informatik
5
1 Datenbanksysteme
1.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . .
1.2 Datenbankentwurf . . . . . . . . . . . . . . . . . . .
1.3 Das relationale Modell . . . . . . . . . . . . . . . . .
1.4 SQL . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.5 Datenintegrität . . . . . . . . . . . . . . . . . . . . .
1.6 Entwurfstheorie (Normalformen) . . . . . . . . . . .
1.7 Transaktionen . . . . . . . . . . . . . . . . . . . . . .
1.8 Objektrelationale und objektorientierte Datenbanken
1.9 Data Warehousing . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7
7
8
10
12
13
13
15
16
17
2 Compilerbau
2.1 Allgemeines . . . . . . . . . . . . . . . .
2.2 Lexikalische Analyse . . . . . . . . . . .
2.3 Syntaktische Analyse . . . . . . . . . . .
2.4 Semantische Analyse . . . . . . . . . . .
2.5 Codegenerierung und Optimierung . . .
2.6 Übersetzung objektorientierter Sprachen
2.7 Top-Down Parser in Java . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
19
19
20
21
23
23
25
26
. . . . . . .
. . . . . . .
Elicitation)
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
29
29
30
31
31
32
33
33
35
36
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3 Software Engineering
3.1 Allgemeines . . . . . . . . . . . . . . . . . . .
3.2 UML . . . . . . . . . . . . . . . . . . . . . . .
3.3 Ermittlung der Anforderungen (Requirements
3.4 Analyse . . . . . . . . . . . . . . . . . . . . .
3.5 Grobentwurf (System Design) . . . . . . . . .
3.6 Feinentwurf (Object Design) . . . . . . . . . .
3.7 Testen . . . . . . . . . . . . . . . . . . . . . .
3.8 Projektmanagement . . . . . . . . . . . . . .
3.9 Vorgehensmodelle . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4 Objektorientierung
41
4.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.2 Entwurfsmuster . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Literaturverzeichnis
43
II
45
Technische Informatik
5 Rechnerarchitektur
5.1 Allgemeines . . . . . . . . . . . .
5.2 Zentralprozessoren . . . . . . . .
5.3 Hauptspeicher und Verkehrswege
5.4 Ein-/Ausgabewerk . . . . . . . .
.
.
.
.
.
.
.
.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
47
47
52
57
59
3
Inhaltsverzeichnis
5.5
SPEC-Werte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6 Betriebssysteme
6.1 Allgemeines . . . . . .
6.2 Prozesse und Threads
6.3 Deadlocks . . . . . . .
6.4 Speichermanagement .
6.5 I/O . . . . . . . . . . .
6.6 Betriebssystem-Design
6.7 Beispiele . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
63
63
63
69
71
74
74
76
7 Rechnernetze
7.1 Allgemeines . . . . . . . .
7.2 ISO–OSI–Referenzmodell
7.3 Schichtübergreifend. . . .
7.4 Schicht 1 . . . . . . . . . .
7.5 Schicht 2a . . . . . . . . .
7.6 Schicht 2b . . . . . . . . .
7.7 Schicht 3 . . . . . . . . . .
7.8 Schicht 4 . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
79
79
80
82
83
83
86
88
91
.
.
.
.
.
.
.
8 Rechnernetze II
95
8.1 Allgemeines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.2 Hochleistungsnetze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
8.3 Dienstgüte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Literaturverzeichnis
III
101
Theoretische Informatik
103
9 Effiziente Algorithmen und Datenstrukturen
9.1 Allgemeines . . . . . . . . . . . . . . . . . . .
9.2 Mathematische Grundlagen . . . . . . . . . .
9.3 Datenstrukturen . . . . . . . . . . . . . . . .
9.4 Selektieren und Sortieren . . . . . . . . . . .
9.5 Minimale Spannbäume . . . . . . . . . . . . .
9.6 Kürzeste Pfade . . . . . . . . . . . . . . . . .
9.7 Matchings . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
105
105
107
108
120
126
127
129
10 Automaten, Formale Sprachen
10.1 Allgemeines . . . . . . . . . .
10.2 Chomsky 3 . . . . . . . . . .
10.3 Chomsky 2 . . . . . . . . . .
10.4 Chomsky 1 . . . . . . . . . .
10.5 Berechenbarkeit . . . . . . . .
und
. . .
. . .
. . .
. . .
. . .
Berechenbarkeit
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
131
131
132
136
141
142
11 Logik
11.1 Allgemeines . .
11.2 Aussagenlogik .
11.3 Prädikatenlogik
11.4 Beweisideen . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
149
149
149
160
168
Literaturverzeichnis
4
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
171
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
Teil I
Praktische Informatik
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
5
Kapitel 1
Datenbanksysteme
1.1
Allgemeines
1.1.1
Was ist der Unterschied zwischen dem relationalem und anderen Modellen?
Im Gegensatz zu dem satzorientierten hierarchischen und dem ebenfalls satzorientierten Netzwerkmodell
ist das relationale Modell mengenorientiert.
1.1.2
Vergleichen Sie B-Bäume mit Hashing im Kontext von Datenbanken?
Beides wird bei Datenbanken eingesetzt. B-Bäume werden zur Speicherung der eigentlichen Daten
benutzt, da Sie gut mit Daten, die auf Hintergrundspeichern liegen, umgehen können. Hashing wird
bei Indizes gesetzt, da es annähernd O(1) Zugriff erlaubt.
1.1.3
Erklären sie die Begriffe
Datenbankschema/Ausprägung und
intensional/extensional .
Das Datenbankschema legt die Struktur der abgespeicherten Daten fest. Eine Ausprägung ist ein
momentan gültiger Zustand der Datenbasis. Man spricht auch von der intensionalen (Schema) und der
extensionalen (Ausprägung) Ebene einer Datenbank. Der Unterschied entspricht dem von Klasse und
Objekt in der Objektorientierung.
1.1.4
Was ist eine Datenbank?
Eine Datenbasis ist eine Menge von Daten. Angereichert um weitere Daten, die das DBMS zur Erfüllung
seiner Aufgabe benötigt, bilden sie eine Datenbank. Ein DBMS einschliesslich einer oder mehrerer
Datenbanken nennt man Datenbanksystem.
1.1.5
Wie sieht eine relationale Datenbank aus?
Eine relationale Datenbank speichert die Daten in Tabellen.
1.1.6
Welche Schichten gibt es bei einer Datenbank?
Mann kann drei Schichten unterscheiden.
1. Physische Schicht: Hier wird festgelegt, wie die Daten gespeichert werden.
2. Logische Schicht: Auf der logischen Schicht wird in einem Datenbankschema festgelegt, welche
Daten gespeichert werden.
3. Sichten: Durch Sichten werden Teilmengen der gespeicherten Daten bereitgestellt.
Das Schichtenmodell dient der Datenunabhängigkeit, es kann zwei Stufen der Datenunabhängigkeit
gewährleisten:
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
7
Kapitel 1. Datenbanksysteme
Physische Datenunabhängigkeit: Die Modifikation der physischen Speicherstruktur lässt die logische
Schicht unverändert.
Logische Datenunabhängigkeit: Kleinere Änderungen des Datenbankschemas (z. B. Umbenennung
von Attributen) können durch Sichten verborgen werden.
1.1.7
Unterscheiden Sie relationale Datenbanken von objektorientierten Datenbanken.
Die Unterschiede entsprechen ziemlich genau den Erweiterungen des objektrelationalen Modells die in
1.8 beschrieben sind.
1.1.8
Erklären Sie den Unterschied zwischen Entity und Klasse.
Entitäten haben keine Methoden, entsprechen also eher Pascal Records. Ausserdem sind alle Attribute
einer Entität atomar.
1.1.9
Wie kann man Objekte mit einer relationalen Datenbank realisieren?
Die Objekte müssen flach geklopft werden, so dass die Objekteigenschaften sich als atomare Attribute
speichern lassen. Dazu sind i. A. mehrere Relationen nötig. Methoden können nicht abgebildet werden.
1.1.10
Wo gibt es denn in der Mathematik Schlüssel?
Bei Funktionen.
1.1.11
Was ist ein Datenbankschema?
Das Datenbankschema legt die Struktur der abgespeicherten Daten fest.
1.1.12
Was ist ein Datenmodell?
Ein Datenmodell ist ein Satz von abgestimmten Konzepten zur Beschreibung der Repräsentation von
Informationen durch Daten.
1.2
Datenbankentwurf
1.2.1
Was gibt es für Modellierungsmöglichkeiten für Datenbanken?
ER-Modell
semantisches Modell
funktionales Modell
objektorientierte Entwurfsmodelle
1.2.2
Beschreiben Sie das ER-Modell.
Die grundlegenden Modellierungsstrukturen des Modells sind
Entities: Entitäten sind wohl unterscheidbare physisch oder gedanklich existierende Dinge der zu
modellierenden Welt. Im ER-Modell wird eigentlich mit Entitymengen gearbeitet.
Relationships: Beziehungen zwischen Entitäten. Diese Beziehung können Funktionalitäten habe,
z. B. 1:N . Sie können ausserdem durch die (min, max)-Notation noch genauer beschrieben werden.
Attribute: Attribute dienen dazu Entitäten zu charakterisieren.
Rollen: Rollen spezifizieren die Rolle einer Entität in einer Beziehung, dies ist z. B. bei rekursiven
Beziehung nötig.
8
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
1.2. Datenbankentwurf
Erweitert wird das ER-Modell durch:
schwache Entitäten: Schwache (existenzabhängige) Entitäten sind in ihrer Existenz von einer übergeordneten Entität abhängig. Oft sind sie nur in Kombination mit dem Schlüssel der übergeordneten
Entität eindeutig identifizierbar.
Generalisierung: Generalisierung bzw. Spezialisierung kann durch is-a-Beziehung modelliert werden.
Aggregation: Aggregation kann durch part-of -Beziehungen modelliert werden.
1.2.3
Was ist eine Entität?
Entitäten sind wohl unterscheidbare physisch oder gedanklich existierende Dinge der zu modellierenden
Welt.
1.2.4
Wie kann man ein ER-Modell in das relationale Modell überführen?
Alles was mit dem ER-Modell modelliert wurde, muss (so weit möglich) in Relationen überführt werden.
Entitäten: straight-forward!
Beziehungen: Zuerst werden alle Beziehungen in Relationen umgesetzt, dies wird später noch verfeinert. Die Relation erhält alle Schlüssel-Attribute der beteiligten Entitäten sowie alle Attribute
der Beziehung. Möglicherweise müssen Attributnamen umbenannt werde um Duplikate auszuschliessen oder die Übersichtlichkeit zu erhöhen. Die Wahl der Schlüssel hängt von der Funktionalität
der Beziehung ab
N :M : Die Menge aller Fremdschlüssel bildet den Schlüssel.
1:N : Als Schlüssel wird der Schlüssel der N Entität gewählt.
1:1: Hier kann man es sich aussuchen.
ternäre Beziehungen: Hier müssen die Schlüssel aller nicht-1-Entitäten aufgenommen werden.
Generalisierung: Das relationale Modell unterstützt Generalisierung nicht, deshalb gibt es nur
suboptimale Lösungen. Mann muss die Information auf die Ober- bzw. Untertypen aufteilen.
Dadurch ist aber keine Vererbung realisiert, um an die ganze Information zu gelangen, muss man
joinen.
Verfeinerung. Das wichtigste ist, dass nur Relationen mit gleichen Schlüsseln zusammengefasst werden
dürfen.
N :M : Diese Beziehungen bleiben als eigenständige Relation erhalten.
1:N : Diese Beziehungen können zusammengefasst werden, wobei die N -Entität um einen Fremdschlüssel erweitert werden muss.
1:1: Hier kann man sich aussuchen in welche Richtung man zusammenfassen möchte. Das ist
natürlich von den Entitäten abhängig, so sollte man z. B. so zusammenfassen, dass möglichst wenige
N U LL-Einträge entstehen.
1.2.5
Gibt es Vererbung im ER-Modell?
Es gibt Generalisierung, die durch is-a-Beziehung realisiert wird.
1.2.6
Was ist der Unterschied zwischen einem UML-Klassendiagramm und einem ER-Diagramm?
Entitäten haben keine Methoden
Attribute von Entitäten können nur atomar sein
Vererbung wird bei ER durch is-a-Beziehung realisiert
Aggregation wird bei ER durch part-of -Beziehung realisiert
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
9
Kapitel 1. Datenbanksysteme
1.2.7
Modellieren Sie eine 3-fach Beziehung.
Vorlesungen
M
Studenten
N
prüfen
1
Professoren
Durch diese Modellierung hat die Relation die Eigenschaften einer partiellen Funktion
prüfen : Studenten × Vorlesungen → Professoren
D. h. jedem Paar (Student, Vorlesung) ist genau ein Prüfer zugeordnet. Ein Student kann sich also
nicht in einer Vorlesung von zwei Professoren prüfen lassen.
1.2.8
Wo kommen im ER-Modell die Fremdschlüssel vor?
Die Fremdschlüssel kommen gar nicht vor. Sie existieren implizit durch Angabe der Relationships.
1.3
Das relationale Modell
1.3.1
Was ist ein Schlüssel?
Eine minimale Teilmenge von Attributen, deren Werte die zugeordnete Entity eindeutig identifizieren.
1.3.2
Was ist ein Primärschlüssel?
Kandidatenschlüssel sind minimale Schlüssel. Gibt es mehrere Kandidatenschlüssel, so wählt man einen
als Primärschlüssel
1.3.3
Was ist ein Fremdschlüssel?
Attribute einer Relation die dazu dienen Tupel einer anderen Relation zu identifizieren, heissen Fremdschlüssel.
1.3.4
Wie werden Beziehung im relationalen Modell dargestellt?
Beziehungen werden wie alles anderen im relationalen Modell durch Relationen (Tabellen) dargestellt.
1.3.5
Geben Sie ein Beispiel für eine Operation auf einer Relation.
Selektion (σ)
Projektion (Π)
Vereinigung (∪)
Differenz (−)
Kreuzprodukt (×)
Umbenennung (ρ)
diverse Joins (1)
Schnitt (∩)
Division(÷)
10
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
1.3. Das relationale Modell
1.3.6
Wie überführt man ternäre Relationships ins relationale Modell?
Die Relation erhält alle Schlüssel-Attribute der an der Beziehung beteiligten Entities und alle Attribute
der Beziehung. Schlüssel der Relation ist die Vereinigung aller Schlüssel von Entitäten, die eine N oder
M Funktionalität haben.
1.3.7
Welche verschiedenen Join-Arten gibt es?
Natürlicher Join: Es wird das Kreuzprodukt gebildet und aus diesem nur diejenigen Tupel interpretiert für die gleichnamige Attribute gleiche Werte haben. Durch eine folgende Projektion wird
jedes Ergebnis nur einmal aufgenommen. Seien R und S zwei Relationen. Wenn R die Attribute
A1 , . . . , Am , B1 , . . . , Bk und S die Attribute B1 , . . . , Bk , C1 , . . . , Cn hat, dann ist der Join wie folgt
definiert:
R 1 S = ΠA1 ,...Am ,R.B1 ,...,R.Bk ,C1 ,...,Ck (σR.B1 =S.B1 ∧...∧R.Bk =S.Bk (R × S))
Der Join-Operator ist assoziativ und kommutativ.
Allgemeiner Join: Beim natürlichen Join werden nur Tupel mit gleichnamigen und gleichwertige
Attributen aufgenommen. Beim allgemeinen Join (oder Theta-Join) kann ein beliebiges Prädikat
angegeben werden. Somit ist der allgemeine Join nichts anderes als ein Kreuzprodukt gefolgt von
einer Selektion:
R 1θ S = σθ (R × S)
Linker äusserer Join: Die Tupel der linken Argumentrelation bleiben in jedem Fall erhalten.
Rechter äusserer Join: Die Tupel der rechten Argumentrelation bleiben in jedem Fall erhalten.
Äusserer Join: Die Tupel beider Argumentrelationen bleiben in jedem Fall erhalten.
Semi-Join (n): Der Semi-Join von L und R ist definiert als
R n S = ΠL (L 1 R)
wobei R die Menge der Attribute von R ist. Das Ergebnis enthält also alle Tupel aus R in unveränderter Form die einen potentielle Joinpartner in S haben.
Semi-Join (o): analog definiert. Es gilt:
RoS =SnR
1.3.8
Erklären Sie Operatoren im Kontext der relationalen Algebra.
Im relationalen Modell werden alle Information in Relationen gespeichert. Relationen sind erst mal nur
Mengen von Tupeln, deswegen können auf ihnen sämtliche Mengenoperationen durchgeführt werden.
Diese Operationen bekommen im Kontext der Datenbankandwendung eine bestimmte Semantik.
1.3.9
Bei welchen Operatoren muss man Duplikate eliminieren?
Bei Projektion (Π) und Vereinigung (∪).
1.3.10
Was ist eine Relation?
Eine Relation ist eine Teilmenge des Kreuzprodukts mehrerer Mengen. Im relationalen Modell werden
Relationen meist als Tabellen dargestellt.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
11
Kapitel 1. Datenbanksysteme
1.4
SQL
1.4.1
Wie würden Sie Vererbung mit Hilfe von SQL
nachbauen?
Generalisierung kann in SQL durch Sichten imitiert werden. Zum Beispiel möchte man die Spezialisierung von Angestellte auf Professoren und Assistenten darstellen. Dabei bestehen zwei Möglichkeiten:
Untertypen als Sicht: Hierbei werden die Untertypen ausschliesslich als Sichten angelegt. Die
Anfragen müssen über recht komplizierte Joins aufgelöst werden.
Obertypen als Sicht: Die Obertypen werden als Sichten angelegt, die ihre Ergebnisse durch Vereinigung von Anfragen an die Untertypen, berechnen.
Die folgenden Beispiele zeigen die Definition der Tabellen und Sichten mit SQL.
Untertypen als Sichten
Obertypen als Sichten
create table Angestellte
( PersNr . . .
Name . . . );
create table Professoren
( PersNr . . .
Name . . .
Rang . . .
Raum . . . );
create table ProfDaten
( PersNr . . .
Rang . . .
Raum . . . );
create table AssiDaten
( PersNr . . .
Boss . . . );
create view Professoren as
select ∗
from Angestellte a, ProfDaten d
where a.PersNr = d.PersNr;
create table Assistenten
( PersNr . . .
Name . . .
Boss . . . );
create view Angestellte as
( select PersNr, Name
from Professoren )
union
( select PersNr, Name
from Assistenten );
create view Assistenten as
select ∗
from Angestellte a, AssiDaten d
where a.PersNr = d.PersNr;
1.4.2
Geben Sie Beispiele für SQL-Anfrage.
select s.∗
from Studenten s
where s.GebDatum <
( select max(p.GebDatum)
from Professoren p );
1.4.3
Wie sieht die allgemeine Syntax einer SQL-Anfrage aus?
select A1 , . . . , An
from R1 , . . . , Rk
where P ;
1.4.4
Wie kann man Anfragen optimieren?
Anfrage können optimiert werden indem die entstehende Zwischenergebnisse möglichst klein gehalten
werden. D. h. man versucht das unvermeidliche Kreuzprodukt möglichst spät zu machen und es dadurch
möglichst klein zu halten.
12
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
1.5. Datenintegrität
1.5
Datenintegrität
1.5.1
Was sind Integritätsbedingungen?
Man unterscheidet zwischen statischen und dynamischen Integritätsbedingungen. Statische Bedingungen müssen von jedem Zustand der Datenbank erfüllt sein. Dynamische Bedingungen müssen an Zustandsübergänge sichergestellt werden. Integritätsbedingung sind:
Schlüsseldefinitionen, keine zwei Tupel mit gleichem Schlüssel dürfen existieren.
Kardinalitäten werden bei dem Übergang ins relationale Modell fest eingebaut.
Referentielle Integrität (keine
Dangling References)
1.6
Entwurfstheorie (Normalformen)
1.6.1
Geben Sie ein Beispiel für eine Relation, die in 2NF aber nicht in 3NF ist.
Ein Verlag speichert alle seine Bücher in der abgebildeten Relation. Diese Relation ist in 2NF da alle
nicht Schlüssel-Attribute voll funktional abhängig vom Schlüssel ArtNr sind. Sie ist aber nicht in 3NF
da die Nicht-Schlüssel-Attribute Titel und Autor abhängig vom Nicht-Schlüssel-Attribut ISBN sind.
ArtNr Titel
Autor
ISBN
Achtung! In der wirklichen Welt ist diese Relation allerdings schon in 3NF. Es gibt nicht für alle Bücher
eine ISBN, deshalb existiert die funktionale Abhängigkeit {ISBN} → {Titel, Autor} nicht.
1.6.2
Was ist
funktionale Abhängigkeit?
Zwei Attributteilmengen α und β von R sind funktional abhängig wenn gilt: Für alle Paare von Tupeln
r, t ∈ R mit r.α = t.α gilt auch r.β = t.β. Wenn also eine funktionale Abhängigkeit α → β besteht,
müssen für alle Tupel, die in allen Attributen von α gleich sind, auch alle Attribute in β gleich sein.
1.6.3
Was ist ’volle funktionale Abhängigkeit?
Die Definition der vollen funktionale Abhängigkeit benötigt man um Schlüssel von Superschlüsseln
abzugrenzen. β ist voll funktional abhängig von α wenn gilt:
1. α → β, d. h. β ist funktional abhängig von α und
2. α kann nicht mehr
verkleinert werden, d. h.
∀A ∈ α : α − {A} 6→ β
Man kann also kein Attribut aus α entfernen ohne die funktionale Abhängigkeit zu zerstören. Wenn
β voll funktional abhängig ist von α schreibt man
•
α → β.
1.6.4
Wann ist eine funktionale Abhängigkeit trivial?
Triviale funktionale Abhängigkeiten sind Abhängigkeiten die automatische erfüllt sind. Nur Abhängigkeiten
der Form
α→β
mit
β⊆α
sind trivial.
1.6.5
Was sind Normalformen?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
13
Kapitel 1. Datenbanksysteme
Normalformen dienen dazu die Güte eines Relationenschemas zu bewerten. Es gibt folgende Normalformen:
1NF : Eine Relation ist in erster Normalform wenn alle Attribute atomare Wertebereiche haben.
2NF : Eine Relation ist in zweiter Normalform wenn alle Nicht-Schlüssel-Attribute voll funktional
abhängig von allen Kandidatenschlüssel sind.
3NF : Die dritte Normalform ist verletzt wenn eine Nicht-Schlüssel-Attribut von einem anderen
Nicht-Schlüssel-Attribut abhängig ist.
Eine Relation R ist in dritter Normalform, wenn für jede für R geltende funktionale Abhängigkeit
der Form α → B mit α ⊆ R und B ∈ R mindestens eine der drei Bedingungen gilt:
B ∈ α, d. h. die funktionale Abhängigkeit ist trivial
Das Attribut B ist in einem Kandidatenschlüssel von R enthalten – also B ist prim.
α ist Superschlüssel von R.
BCNF : Eine Relation R ist in Boyce-Codd Normalform wenn für jede für R geltende funktionale
Abhängigkeit α → β eine der folgenden Bedingung gilt:
β ⊆ α, d. h. die funktionale Abhängigkeit ist trivial.
α ist Superschlüssel von R.
4NF : Eine Relation R mit einer zugeordneten Menge D von funktionalen und mehrwertigen Abhängigkeiten ist in vierter Normalform, wenn für jede mehrwertige Abhängigkeit α →→ β ∈ D +
eine der folgenden Bedingungen gilt.
Die mehrwertige Abhängigkeit ist trivial.
α ist Superschlüssel von R.
1.6.6
Erläutern Sie den Algorithmus zur Zerlegung in 3NF und führen Sie ihn an einem Beispiel vor.
Der folgende Algorithmus zerlegt ein Relationenschema R mit funktionalen Abhängigkeiten F so in
Relationenschemata R1 , . . . , Rn , dass folgende Kriterien erfüllt sind.
R1 , . . . , Rn ist eine verlustlose Zerlegung von R.
Die Zerlegung ist abhängigkeitsbewahrend.
Alle Ri sind in dritter Normalform.
Algorithmus:
1. Bestimme die kanonische Überdeckung Fc zu F . Das geht so:
a)
b)
c)
d)
Linksreduktion der funktionalen Abhängigkeiten
Rechtsreduktion der funktionalen Abhängigkeiten
Entfernung funktionaler Abhängigkeiten der Form α → ∅
Zusammenfassung funktionaler Abhängigkeit mit gleichen linken Seiten
2. Für jede funktionale Abhängigkeit α → β ∈ Fc :
Kreiere eine Relationenschema Ra := α ∪ β
Ordne Ra die funktionalen Abhängigkeiten. Fα := {a0 → β 0 ∈ Fc | α0 ∪ β 0 ⊆ Ra } zu.
3. Falls eines der in Schritt 2 erzeugten Schemata Ra einen Kandidatenschlüssel von R bzgl Fc enthält,
sind wir fertig. Ansonsten wähle einen Kandidatenschlüssel κ ⊆ R aus und definiere folgendes
zusätzliche Schema:
Rκ := κ
Fκ := ∅
4. Eliminiere diejenigen Schemata Ra , die in einem anderen Relationenschema Ra0 enthalten sind,
d. h.
Ra ⊆ R a0
1.6.7
14
Warum bringt man Relationen in Normalformen?
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
1.7. Transaktionen
Bei schlechten Relationenschemata kann es zu folgenden Anomalien kommen
Updateanomalie Wenn Informationen redundant gespeichert werden, müssen sie bei einer Änderung
an alle Stellen geändert werden. Wenn dies nicht geschieht, treten Problem auf. Selbst wenn dies
sichergestellt wird, kostet es Speicherplatz und Performance.
Einfügeanomalie Wenn in einem Entwurf Informationen zweier Entitytypen vermischt werden, so
ergeben sich Problem wenn man nur eine der Entitäten anlegen will. Die anderen Werte müssen
dann mit NULL-Werten aufgefüllt werden.
Löschanomalie Wen Information bzgl. eines der beiden vermischten Entitytypen gelöscht werden
kommt es zum Verlust von Informationen bzgl. des anderen Typen.
Alle diese Anomalien sind darauf zurückzuführen, dass nicht zusammenpassende Information in einer
Relation gespeichert werden. Normalisierung soll das verhindern.
1.6.8
Ist die Zerteilung (3NF) verlustlos und abhängigkeitsbewahrend?
Ja. Die Relation R wurde in die Relationen R1 , . . . , Rn zerlegt. Mann kann aber alle Information die in
der Ausprägung R enthalten war aus den Ausprägungen R1 , . . . Rn rekonstruieren und für R geltenden
funktionalen Abhängigkeiten sind auf R1 , . . . , Rn übertragbar.
1.6.9
Was sind die
Armstrong-Axiome?
Die Armstrong-Axiome sind:
Reflexivität: Falls β eine Teilmenge von α ist, dann gilt immer α → β. Insbesondere gilt also immer
α → α.
Verstärkung: Falls α → β gilt, dann gilt auch α ∪ γ → β ∪ γ.
Transitivität: Falls α → β und β → γ gilt, dann gilt auch α → γ.
Mit den Armstrong-Axiomen kann die Hülle F + einer Menge F von funktionalen Abhängigkeiten bestimmt werden.
1.7
Transaktionen
1.7.1
Was ist eine Transaktion?
Aus der Sicht des Datenbankbenutzers ist eine Transaktion eine Arbeitseinheit, die eine bestimmte
Funktion erfüllt. Aus der Sicht des DBMS ist eine Transaktion eine Folge von Lese-und Schreiboperationen abgeschlossen durch ein abort oder commit.
1.7.2
Welche Eigenschaften müssen Transaktionen erfüllen?
siehe 1.7.3
1.7.3
Was bedeutet das Akronym ACID?
Das Akronym steht für die vier wichtigsten Forderungen an Transaktionen
Atomicity: Eine Transaktion muss atomar, also ununterbrechbar sein. Entweder werden keine oder
alle Änderungen in der Datenbasis festgeschrieben (alles-oder-nichts-Prinzip).
Consistency: Eine Transaktion muss bei Beendigung einen konsistenten Zustand hinterlassen, anderenfalls wird sie komplett zurückgenommen. Während der Ausführung der Transaktion können
teilweise Konsistenzbedingungen verletzt werden.
Isolation: Nebenläufige Transaktionen dürfen sich nicht gegenseitig beeinflussen. Für eine Transaktion muss es so aussehen, als sei sie die einzige auszuführende Transaktion.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
15
Kapitel 1. Datenbanksysteme
Durability: Die Wirkung einer erfolgreich abgeschlossenen Transaktion muss dauerhaft in der Datenbasis festgeschrieben werden. Die bereits ausgeführten Teile einer abgebrochenen Transaktion
müssen vollständig rückgängig gemacht werden.
1.7.4
Welche Probleme gibt es bei der Ausführung von Transaktion und welche Lösungen gibt es?
Probleme beim Einbenutzerbetrieb:
Das DBMS kann abstürzen. Die Recovery muss dafür sorgen, den ursprünglichen Zustand wieder
herzustellen.
Am Ende einer Transaktion zeigt sich, dass Konsistenzbedingungen verletzt werden. Bisher durchgeführt Operationen müssen Rückgängig gemacht werden.
Probleme beim unkontrollierten Mehrbenutzerbetrieb:
Lost update: Durch ungeschickte Verzahnung mehrere Transaktionen können Änderungen verloren
gehen. Die Mehrbenutzersynchronisation muss das ausschliessen.
Dirty read : Durch ungeschickte Verzahnung mehrere Transaktionen liest eine Transaktion Daten,
die noch nicht freigegeben wurden. Die Mehrbenutzersynchronisation muss das ausschliessen.
Phantomproblem: Eine Transaktion liest während ihres Ablaufs bestimmte Daten zweimal. Zwischen dem ersten und zweiten Zugriff fügt eine andere Transaktion ein neues Datum ein, das mit
berücksichtigt werden muss. Dadurch unterscheiden sich der erste und der zweite Zugriff, da beim
zweiten Zugriff das neu eingefügte Phantom mit gelesen wurde. Die Mehrbenutzersynchronisation
muss das ausschliessen.
Probleme beim kontrollierten Mehrbenutzerbetrieb:
Verklemmungen: Mehrere Transaktionen können in einen Deadlock geraten.
1.7.5
Was ist
Serialisierbarkeit?
Beim Konzept der Serialisierbarkeit werden die Vorzüge der seriellen Ausführung (Isolation) mit den
Vorteilen des Mehrbenutzerbetriebs (bessere Auslastung) kombiniert. Eine serialisierbare Ausführung
mehrer Transaktionen entspricht einer kontrollierten Verzahnung und zwar so, dass das Ergebnis dem
des echten seriellen Ausführens entspricht.
1.7.6
Was ist das Serialisierbarkeitstheorem?
Das Serialisierbarkeitstheorem besagt, dass eine Historie H genau dann serialisierbar ist, wenn ihr
Serialsierbarkeitsgraph SG(H) azyklisch ist.
Eine Serialisierung entspricht einer topologischen Sortierung des Serialsierbarkeitsgraphen. Es gibt keine
topologische Sortierung, falls dieser Zyklen enthält.
1.8
Objektrelationale und objektorientierte Datenbanken
1.8.1
Was ist eine objektrelationale Datenbank?
Das objektrelationale Modell erweitert das relationale Modell wie folgt:
Mengenwertige Attribute: Attribute müssen nicht mehr Atomar sein, man erlaubt Mengen als
Attribute.
Typendeklaration: Das objektrelationale Modell erlaubt das erstellen eigener Datentypen.
Referenzen: Attribute können direkt Referenzen auf Objekte haben. Dadurch ist man nicht mehr
auf Fremdschlüssel angewiesen. Ausserdem können N :M -Beziehungen durch eine Menge von Referenzen aufgelöst werden.
Objektidentität: Voraussetzung für Referenzen ist die eindeutige Identifizierbarkeit von Objekten.
16
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
1.9. Data Warehousing
Pfadausdrücke: Wenn Referenzen erlaubt sind, muss die Anfragesprache auch Pfadausdrücke unterstützen.
Vererbung
Methode: Klassen (bzw. Objekten) können Methoden zugeordnet werden.
1.8.2
Was versteht man unter
Objektidentität?
Im Gegensatz zu relationalen Modell braucht man beim objektorientierten Modell keine Schlüssel zu
verwenden um ein Objekt anzusprechen. Jedes Objekt hat eine systemweit eindeutig Identität, die
automatisch generiert wird und sich während der Objektlebenszeit nicht ändert.
1.9
Data Warehousing
1.9.1
Was ist Data Warehousing?
Eine Data Warehouse ist eine Datenbank die historische Unternehmensdaten hält, es ist eine OLAPAnwendung (Online Analytical Processing). Der Datenbestand des Data Warehouses wird periodisch
mit Informationen aus den operationalen Datenbanken des Unternehmens aufgefrischt. Das Data Warehouse dient der Analyse langfristiger Entwicklungen und daher zur Entscheidungsunterstützung.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
17
Kapitel 2
Compilerbau
2.1
Allgemeines
2.1.1
Geben Sie einen Überblick über die Struktur eines Compilers.
Quellprogramm
Lexikalische Analyse
Token
Frontend
Syntaxanalyse
Syntaxbaum
Semantische Analyse
Zwischencode
Optimierung
Zwischencode
Backend
Codeerzeugung
Code
lexikalische Analyse: Das Quellprogramm wird mit einem Scanner in eine Folge von Tokens zerlegt.
Syntaxanalyse: Aus diesen Token erzeugt der Parser einen Syntaxbaum entsprechende der Syntax
der Programmiersprache.
semantische Analyse: In der semantischen Analyse wird der Syntaxbaum hinsichtlich semantischer
Korrektheit (z. B. Typinformationen) geprüft.
Optimierung: In der Optimierungsphase wird der erzeugte Zwischencode optimiert.
Codeerzeugung: Aus dem optimierten Zwischencode wird in Maschinencode erzeugt. Der Zielcode
kann nochmal optimiert werden.
2.1.2
Welche Fehler werden an welchen Stellen erkannt?
lexikalische Fehler : Lexikalische Fehler, z. B. ungültige Zeichen oder ungültige Bezeichner werden
vom Lexer erkannt.
Syntaxfehler : Der Parser erkennt Syntaxfehler.
semantische Fehler : Semantische Fehler, z. B. Typfehler oder ungültige Methodenparameter werden
bei der semantischen Analyse erkannt.
2.1.3
In welchen Phasen finden Optimierungen statt?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
19
Kapitel 2. Compilerbau
In der Optimierungsphase. Man unterscheidet zwischen der Optimierung von Zwischencode und der
Optimierung von Zielcode.
2.1.4
Was sind Attribute?
Attribute beschreiben Eigenschaften von Syntaxknoten.
2.1.5
Wie funktioniert die Informationsübergabe zwischen Scanner und Parser?
Über Tokens.
2.1.6
Was ist ein Token?
Ein Token ist eine Folge von Zeichen die bedeutungsmässig zusammengehören.
2.1.7
Welche Fehler kann das Laufzeitsystem erkennen?
Indexüberschreitungen bei Arrays
Cast-Exceptions (OO)
Null-Pointer-Exceptions
2.1.8
Welche Fehler werden nicht gefunden?
Logische Fehler.
2.1.9
Was ist Bootstrapping?
Beim Bootstrapping wird ein Compiler für eine neue Programmiersprache Schritt für Schritt entworfen.
Zuerst wird in Maschinensprache ein Compiler entworfen, der nur eine Teilmenge der Sprache beschert,
mit diesem wird dann ein Compiler geschrieben, der schon etwas mehr kann, usw.
2.2
Lexikalische Analyse
2.2.1
Was ist screenen?
Entfernung von Leerzeichen, Zeilenumbrüche, Tabstopps, . . .
2.2.2
Kann man auch Leerzeichen in den Identifaktoren haben?
Ja, z. B. bei Fortran.
2.2.3
Was verwendet man zur lexikalischen Analyse?
Einen endlichen Automaten.
2.2.4
Wie unterscheidet man Literale von Bezeichnern?
Durch Sonderzeichen wie Anführungsstriche.
2.2.5
Dürfen Schlüsselwörter auch Bezeichner sein?
Es gibt Sprachen, wo dies erlaubt ist, z. B. PL/1.
20
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
2.3. Syntaktische Analyse
2.3
Syntaktische Analyse
2.3.1
Entwerfen Sie einen Top-Down-Parser für folgende Grammatik:
→
E
E+T | T
→ T ∗F | F
→ (E) | id
T
F
wobei E das Startsymbol ist.
1. Elimination der Links-Rekursivität.
Diese Grammatik ist links-rekursiv, dass kann zu Endlosschleifen im Top-Down-Parser führen, daher
muss die Links-Rekursivität beseitigt werden:
E
E0
T
T0
F
→ T E0
→ +T E 0 | → FT0
→ ∗F T 0 | → (E) | id
2. Recursive Decent Parser in Java. Abschnitt 2.7 zeigt eine Java-Implementierung des Parsers. Für
jedes Nicht-Terminal existiert eine Methode. E 0 und T 0 heissen in der Java-Version E1 und E2.
Statt Bezeichner erkennt der Parser Ziffern.
2.3.2
Was für Sprachen verwendet man und wieso?
Man verwendet deterministisch kontextfreie Sprachen, da deren Mächtigkeit annähernd ausreichend ist
und das Wortproblem in linearer Zeit gelöst werden kann.
2.3.3
Was ist der Unterschied zwischen LL(k) und LR(k) und was ist mächtiger?
Ein LR-Parser erkennt, dass für die Ableitung eines Wortes die Produktion A → β angewandt wurde,
nachdem er alles gesehen hat, was aus den Symbolen von β abgeleitet wurde – denn zu jedem Symbol
aus β liegt der Ableitungsbaum bereits vor (auf dem Stack) – sowie die nächsten k Zeichen der Eingabe.
Ein LL-Parser muss die Entscheidung treffen nachdem er nur die ersten k Zeichen des aus β abgeleiteten
Wortes gesehen hat. Daher können LR-Grammatiken mehr Sprachen als LL-Grammatiken beschreiben,
es gilt L(LL) ⊂ L(LR).
2.3.4
Was ist eine attributierte Grammatik?
Attributierte Grammatiken sind formale Beschreibungen von Übersetzungsprozessen und werden zur
Spezifikation und zur Generierung von Übersetzern verwendet. Sie beschreiben, wie die Knoten des
erzeugten Syntaxbaums mit Attributen ’dekoriert’ werden, die schliesslich das Übersetzungsergebnis
darstellen. Zum Beispiel definiert die Produktion
VarDecl↑list = ’var’ NameList↓type↑list ’:’ Type↑type ’;’
folgende semantische Aktionen:
NameList.type := Type.type;
VarDecl.list := NameList.list;
2.3.5
Was ist eine LALR-Grammatik?
Eine LALR-Grammatik kann mit einem LALR-Parser erkannt werden. LALR steht für lookahead LR.
LALR stellt einen Kompromiss in Sachen Mächtigkeit und Aufwand zwischen SLR und kanonischer
LR da.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
21
Kapitel 2. Compilerbau
2.3.6
Wie kann man Linksrekursionen beseitigen?
Um die Linksrekursivität von A zu beseitigen, geht man wie folgt vor:
1. Man teilt alle A-Produktionen in zwei Gruppen auf.
rekursiven, in die andere, die nicht-links-rekursiven:
A
A
→
→
In die eine Gruppe kommen die links-
Aα1 | Aα2 | . . . | Aαm
β 1 | β2 | . . . | β n
2. Dann ersetzt man die ursprüngliche A-Produktionen durch
A → β 1 A0 | β2 A0 | . . . | β n A0
wobei A0 eine neue Variable ist. Für A0 werden folgende Produktionen eingefügt.
A → α 1 A0 | α2 A0 | . . . | α m A0 | Wichtig ist die -Alternative.
Frage 2.3.1 zeigt ein einfaches Beispiel. Diese Vorgehensweise beseitigt nur direkte Links-Rekursionen.
2.3.7
Welche Fehler erkennt der Parser?
Syntaxfehler.
2.3.8
Ist LR(k) mächtiger als LR(1)?
Nein. Die Sprachklassen LR(1), LR(2), . . . sind alle gleich mächtig. Es sind die Sprachen, die von
einem deterministischen Kellerautomaten über Endzustände erkannt werden. LR(0)-Sprachen werden
von einem deterministischen Kellerautomaten über den leeren Keller erkannt.
2.3.9
Erzeugt eine kontextsensitive Grammatik auch einen Baum?
Nein. Typ 1 Grammatiken erzeugen Ableitungsgraphen.
2.3.10
Was bedeutet mehrdeutig und welche Probleme sind damit verbunden?
Eine Grammatik ist mehrdeutig wenn es für ein Wort mehrere, verschieden Ableitungsbäume gibt.
Programmiersprachen sollten nicht mehrdeutig sein, da mehrere Ableitungsbäume meistens auch verschiedenen Bedeutungen entsprechen.
2.3.11
Geben Sie eine Grammatik für arithmetische Ausrücke mit Klammerung, Addition und Multiplikation
an.
expr
expr
expr
op
op
2.3.12
→
→
→
→
→
expr op expr
( expr )
num
+
∗
Welche Fehlerbehandlungsstrategien gibt es?
panic mode: Nachdem der Parser einen Fehler gefunden hat, überspringt er folgende Tokens bis zu
einem ausgezeichneten Synchronisationstoken, z. B. das Semikolon.
phrase level : Der Parser ’behebt’ Fehler in dem er Fehlerhafte Token durch gültige ersetzt, also
z. B. eine Komma durch ein Semikolon ersetzt.
22
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
2.4. Semantische Analyse
error productions: Falls die Fehler gut bekannt sind, können eigene Produktion für Fehler definiert
werden.
2.3.13
Kann jeder Parser nach der Recursive-Decent-Methode implementiert werden?
Nein. Die Recursive-Decent-Methode funktioniert nur bei LL-Grammatiken, diese müssen ausserdem
frei von Linksrekursionen sein, sonst kann es zu Endlosschleifen kommen.
2.4
Semantische Analyse
2.4.1
Was passiert bei der semantischen Analyse?
Die semantische Analyse erfüllt zwei Aufgaben:
Überprüfung des Syntaxbaums auf Fehler.
Zusätzlich zur kontextfreien Grammatik unterliegen Programmiersprachen noch weiteren, kontextsensitiven Regeln, wie z. B.
Bezeichner müssen vor der ersten Verwendung deklariert werden
Zuweisungen müssen typkorrekt sein
Beim Methodenaufruf müssen Anzahl und Typ der Parameter stimmen
Diese Bedingungen müssen während der semantische Analyse überprüft werden, da der (auf kontextfreie Sprachen beschränkte) Parser dies nicht erledigen kann.
Vorbereitung der Codeerzeugung. In der semantischen Analyse kann die Codeerzeugung vorbereitet
werden, indem z. B. Adressen für Variablen (lokal) vergeben werden.
2.4.2
Was ist eine Symboltabelle?
Die Symboltabelle hält für jeden Bezeichner seine Deklarationsinformation. Beim ersten Vorkommen
eines Bezeichner wird ein Symboltabelleneintrag angelegt auf den bei späteren Typüberprüfungen zugegriffen werden kann. Symboltabellen werden häufig mit Hashing implementiert.
2.4.3
Welche Arten von Attributen gibt es?
Es gibt
erzeugte Attribute (synthesized): Attribute werden als erzeugt bezeichnet, wenn der Wert eines
Attributs an einem Parsebaum Knoten von Attributen der Kinder dieses Knotens abhängt. Erzeugte
Attribute können bei einem einzigen Bottom-Up Durchlauf berechnet werden.
vererbte Attribute (inherited): Der Wert von vererbten Attributen wird aus Attributen des Vaterknotens oder von Geschwisterknoten berechnet.
2.4.4
Geben Sie Beispiele für Attribute.
Typinformation
Code
Deklarationsinformation
Adressen bzw. Stackinformation
2.5
Codegenerierung und Optimierung
2.5.1
Welche Rolle spielen Attribute bei der Codegenerierung?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
23
Kapitel 2. Compilerbau
Während der semantischen Analyse kann bereits Vorarbeit für die Codegenerierung geleistet worden
sein, so können bereits Adressen für die Variablen errechnet worden sein.
Ausserdem besteht die Möglichkeit, den Code nicht direkt auszugeben, sondern in Codeattributen des
Syntaxbaumes zu speichern. Der Wurzelknoten enthält dann den ganzen Code.
2.5.2
Welche Optimierungsmöglichkeit gibt es bei der Codegenerierung
Konstantenfaltung: Konstantenausdrücke können zur Compilezeit berechnet werden. Das ist vor
allem wichtig für Verbesserungen, die der Programmierer nicht beeinflussen kann. Beispiel Zugriff
auf das Arrayelement a[3]:
memory[base + offset(a) + 3 · elemSize]
⇒
memory[base + constant]
algebraische Vereinfachungen: Teure Operationen durch billige ersetzen, z. B. Division und Multiplikation durch Bit-Shifts.
Copy Propagation: Bei Zuweisungen der Form x := y kann in der Folge jedes Vorkommen von x
durch y ersetzt werden, solange der Wert von x sich nicht ändert.
3+5·z
x
:=
y
z
:= 3 · n
:= x
Hier kann die Variable x weg optimiert werden:
y
:=
z
:=
3·n
3+5·z
Entfernung von totem Code: Zum Beispiel Zuweisungen an Variablen, die nicht mehr benutzt
werden oder Code der in einem Ast eines If-Then-Statements liegt, das nicht erreicht werden
kann.
Auflösung von Schleifeninvarianten: Zuweisungen innerhalb einer Schleife, die nicht vom Schleifenzähler abhängen können aus der Schleife herausgezogen werden.
Befehlsanordnung: Befehle sollten nach Möglichkeit so angeordnet sein, dass sie das Pipelining
moderner Prozessoren unterstützen.
Registervergabe: Variablen sollte so auf Register und Hauptspeicher verteilt sein, dass möglichst
selten auf den Hauptspeicher zugegriffen wird.
2.5.3
Was ist ’Peephole’-Optimierung?
Bei der ’Peephole’-Optimierung wird immer nur ein kurzes Stück Code angeschaut und dort verschiedene
Optimierungen durchgeführt. Diese kurze Stück ist das ’Peephole’. Typische Anwendungsfelder für
’Peephole’-Optimierung sind:
Entfernung redundanter Anweisungen
Kontrollfluss-Optimierung
algebraische Vereinfachungen
2.5.4
Wie funktioniert die Registervergabe nach Aho-Johnson?
Der Registervergabealgorithmus nach Aho-Johnson arbeitet nach dem Prinzip des dynamischen Programmierens.
2.5.5
Was sind die Ausgangs- und Zieldatenstrukturen?
Sowohl Ein- wie Ausgabe der Optimierung ist eine Zwischensprache. Meist verwendet die Zwischensprache einen Drei-Adress-Code der in Tupel gespeichert wird. Diese Zwischensprache ähnelt einer
Assemblersprache.
24
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
2.6. Übersetzung objektorientierter Sprachen
2.6
Übersetzung objektorientierter Sprachen
2.6.1
Welchen Unterschiede gibt es zwischen Compilern für objektorientierte Sprachen und Compilern für
prozeduralen Sprachen?
Entsprechend der Phasen:
lexikalische Analyse: keine Unterschiede.
Syntaxanalyse: keine Unterschiede.
semantische Analyse: Die Typanalyse wird komplizierter, da die Klassenstruktur (Vererbung)
berücksichtigt werden muss. Der Compiler muss überprüfen ob Vererbung, Interface-Implementierung,
usw. korrekt programmiert ist.
Optimierung: siehe 2.6.2.
Codeerzeugung: Bei objektorientierten Programmiersprachen kommt es aufgrund der Polymorphie
viel öfter zu Fällen, in denen nicht während der Compilezeit gebunden werden kann (dynamische
Bindung).
2.6.2
Was für spezielle Methode zur Optimierung gibt es bei OO-Compilern?
Man versucht die Bindungen so gut es geht zur Compile-Zeit zu erledigen, dadurch erspart man sich
aufwendiges Methoden suchen. Im einfachsten Falle bindet man nur dynamisch, im kompliziertesten
macht man eine komplette Datenflussanalyse und versucht damit die Zahl der dynamischen Bindungen
klein zu halten. Dies ist aber zu aufwendig.
2.6.3
Erklären Sie an einem Beispiel nochmal genau den Unterschied zwischen dynamischer und statischer
Bindung. Wann bindet Java statisch und wann dynamisch?
Das Beispiel macht nochmal alles klar. Es gibt eine Klassenhierarchie mit zwei Klassen, Oberklasse ist
Shape, Unterklasse ist Circle. Ausserdem gibt es noch eine Klasse Test mit zwei Methoden die je
nach Parameter (Shape oder Circle) einen unterschiedlichen String zurückgeben.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
25
Kapitel 2. Compilerbau
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2.7
class Shape {
private String name;
public String toString(){
return "Shape";
}
}
class Circle extends Shape {
public String toString(){
return "Circle";
}
}
class Test {
public String print(Shape shape) {
return "Test: Shape";
}
public String print(Circle circle) {
return "Test: Circle";
}
In Zeile 29–31 wird eine Variable werden drei
Variablen deklariert. shape1 und shape2 haben den Typ Shape. circle hat den Typ
Circle. Die Variabel shape1 und circle sind
jeweils Objekten zugeordnet, die ihrem statischen Typ entsprechen. Der Variablen shape2
ist ein Kreis zugeordnet, somit eine Instanz einer Unterklasse. Wenn man dieses Programm
nun laufen lässt erhält man folgende Ausgabe:
Dynamische Bindung
Shape
Circle
Circle
Statische Bindung
Test: Shape
Test: Circle
Test: Shape
Erst mal zu den Ausgabe die die dynamische
Bindung betreffen. Die ersten beiden Ausgabe
}
sind klar, hier wird einfach die toString()Methode der Klassen Shape bzw. Circle aufpublic class DynBind {
gerufen. Die dritte Ausgabe ist nun interespublic static void main(String argv[]) {
sant. Obwohl die Variable vom statischen Typ
Shape ist, wurde offensichtlich die Methode
Test test = new Test();
der Klasse Circle aufgerufen. Die MethodenShape shape1 = new Shape();
bindung hängt also von der aktuellen Instanz
Circle circle = new Circle();
ab. Natürlich könnte in diesem einfach Fall
Shape shape2 = circle;
bereits Compiler die Zusammenhänge erkennen und die Methode statisch binden. Es gibt
System.out.println("Dynamische Bindung"); aber viel komplexere Situationen in denen das
System.out.println(shape1);
tatsächlich nur zur Laufzeit möglich ist oder
System.out.println(circle);
der Compiler müsste eine sehr aufwendige DaSystem.out.println(shape2);
tenflussanalyse machen (und selbst dann geht
System.out.println("Statische Bindung"); es nicht immer).
Java bindet also die Methoden dynamisch an
System.out.println(test.print(shape1));
die Objekte. Der zweite Teil der Ausgabe zeigt,
System.out.println(test.print(circle));
System.out.println(test.print(shape2));
dass dies bei den Methodenparametern nicht so
}
ist. Unabhängig von der Instanz, der die Va}
riable zugeordnet ist, wird immer die statische
Typdefinition verwendet.
Top-Down Parser in Java
Dieser Parser arbeitet nicht auf Tokens, die vom Scanner kommen, sondern direkt auf Zeichen. Da in der
beschreibenden Grammatik ausserdem -Produktion sind, kommt der Parser nicht mit unbekannten Zeichen
zurecht.
26
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
2.7. Top-Down Parser in Java
static void nextToken() {
lookahead++;
}
static boolean match(char token) {
public class TopDownParser {
static char[] input;
static int lookahead;
if (lookahead >= input.length) return false;
static void ntE() throws ParseException {
printLA();
System.out.println("E -> T E2");
ntT();
ntE2();
}
static void ntE2() throws ParseException {
printLA();
System.out.print("E2 ->");
if (match(’+’)) {
System.out.println(" + T E2");
ntT();
ntE2();
}
else {
System.out.println(" e");
}
if (token==input[lookahead]) {
nextToken();
return true;
}
else {
return false;
}
}
static boolean matchDigit() {
if (lookahead >= input.length) return false;
if (Character.isDigit(input[lookahead])) {
nextToken();
return true;
}
else {
return false;
}
}
static void ntT() throws ParseException {
printLA();
System.out.println("T -> F T2");
ntF();
ntT2();
}
static void ntT2() throws ParseException {
printLA();
System.out.print("T2 ->");
if (match(’*’)) {
System.out.println(" * F T2");
ntF();
ntT2();
}
else {
System.out.println(" e");
}
}
static void ntF() throws ParseException {
printLA();
System.out.print("F ->");
if (match(’(’)) {
System.out.println(" ( E )");
ntE();
match(’)’);
}
else if (matchDigit()) {
System.out.println(" digit");
}
else
throw new ParseException(lookahead);
}
static void printLA() {
System.out.print(lookahead);
if (lookahead < input.length)
System.out.print
("["+input[lookahead]+"] | ");
else
System.out.print ("[e] | ");
}
public static void main(String argv[]) {
input = argv[0].toCharArray();
lookahead=0;
try {
ntE();
System.out.println("k");
}
catch (ParseException ex) {
System.out.println
("\nParseException at position: "
+ ex.pos);
}
}
static class ParseException extends Exception {
public int pos;
public ParseException(int pos){
super("ParseException at position: " + pos);
this.pos=pos;
}
}
}
}
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
27
Kapitel 3
Software Engineering
3.1
Allgemeines
3.1.1
Was sind Komponenten und wie sind sie definiert?
Eine Komponente ist ein physischer und austauschbarer Teil eines Systems der durch eine Schnittstelle
spezifiziert ist. Beispiele sind Klassenbibliotheken, Frameworks und Binärprogramme.
3.1.2
Was ist in einer Schnittstelle definiert?
Eine Schnittstelle ist ein Übergang zwischen zwei Funktionseinheit mit vereinbarten Regeln für die
Übergabe von Daten oder Signalen.
3.1.3
Was wäre den in Java ein Modul und was eine Komponente?
Es gibt keine vernünftige Trennung von Modul und Komponente.
3.1.4
Was sind CASE-Tools?
CASE steht für Computer Aided Software Engineering. CASE-Tools sind Programm die den Entwickler
bei den verschieden Phasen des Engineerings unterstützen. Darüber hinaus unterstützen CASE-Tools
auch Bereiche wie Projektkommunikation, Dokumentation,. . . .
3.1.5
Um welche Aspekte geht es beim Software-Engineering?
Der Titel des Bruegge Buch sagt es:
3.1.6
Conquering Complex And Changing System .
Wie ist der Aufwand dabei verteilt?
Man rechnet Ungefähr 10% für Analyse, 20% für Entwurf, 20% für Implementierung und 50% für Testen
und Wartung.
3.1.7
Sie haben ein OO-Modell bis runter zu den Objekten, wie geht es dann weiter?
Jetzt folgt die Implementierungsphase mit anschliessendem Testen.
3.1.8
Was ist ein Modul?
Module sind physische Container in denen man Klassen und Objekte des logischen Designs definiert.
3.1.9
Wie kann man Daten modellieren?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
29
Kapitel 3. Software Engineering
Zum Beispiel mit UML oder ER-Diagrammen.
3.1.10
In welche Phasen organisiert man ein Softwareprojekt?
Softwareentwicklung besteht normalerweise aus diesen fünf Aktivitäten:
Ermittlung der Anforderungen (Requirements Elicitation). Kunde und Entwickler definieren die
Aufgabe des Systems. Das Ergebnis kann eine Beschreibung des Systems in Form von Use Case
und Akteuren sein. Es werden funktionale so wie nicht-funktionale Anforderung herausgearbeitet.
Analyse (Analysis). Das Ziel der Analyse ist es ein Modell aufzustellen das das System komplett
beschreibt und alle Anforderung gerecht wird. Bei diesem Schritt befindet man sich noch komplett
in der Problemdomäne. Es gibt natürlich Ausnahmen wie Pseudo-Requirements. Wenn der Kunde
fordert, dass in Java implementiert wird, ist das eine Anforderung an die Lösungsdomäne.
Grobentwurf (System Design). Die Architektur des Systems wird festgelegt, d. h. Designziele
werden definiert und das System in kleinere Subsysteme aufgeteilt. Ausserdem wird die Zuordnung
von Software auf Hardware festgelegt.
Feinentwurf (Object Design). Aufgabe dieser Phase ist es die Kluft zwischen dem Grobentwurf und
der Implementierung zu schliessen. Ausserdem werden hier Entscheidung bzgl. dem Einsatz von
Fertigprodukten getroffen. Das Ergebnis ist ein detailliertes Objekt Modell mit präzisen Beschreibungen für alle Elemente.
Implementation. Jetzt wird das Objekt Modell in Code umgesetzt. Unit-Tests sollten hier stattfinden.
Test. Integration- und System Tests.
Operation und Wartung
3.1.11
Nochmal Subsystem, Paket, Komponente?
Bezüglich der genauen Definition von Subsystem, Paket, Komponente und Modul herrscht alles andere
als Einigkeit. UML definiert sie so:
Subsystem: Ein Subsystem ist ein Teil eines Gesamtsystems, das nach aussen durch eine Schnittstelle
definiert ist und die Struktur und die Zusammenarbeit seiner Einzelteile versteckt.
Paket: Ein Paket ist eine lose Ansammlung von Modellelementen, das nicht durch eine Schnittstelle
definiert sein muss und sein Inneres nicht kapseln muss.
Komponente: Ein Komponente ist eine ausführbare und austauschbare Softwareeinheit mit definierter Schnittstelle und eigener Identität.
UML definiert keine Module, aber das dürfte wohl am ehesten den Komponenten entsprechen.
3.2
UML
3.2.1
Wie definiert man Semantik mit der UML?
Mit der OCL können Constraints beschrieben werden.
3.2.2
Wenn man eine Software-Architektur mit UML beschreibt, welche Verbindungsrelationen sind da brauchbar?
So ziemlich alle Arten von Assoziationen inklusive Aggregation und Kompositionen.
3.2.3
Was ist UML?
Die UML ist eine Sprache und Notation zur Spezifikation, Konstruktion, Visualisierung und Dokumentation von Modellen für Softwaresysteme.
30
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
3.3. Ermittlung der Anforderungen (Requirements Elicitation)
3.2.4
Welche Diagrammarten gibt es in der UML?
Use Case Diagramme
Klassendiagramme
Sequenzdiagramme
Aktivitätsdiagramme
Kollaborationsdiagramme
Zustandsdiagramme
Verteilungsdiagramme
3.2.5
Vergleiche Sie UML-Klassendiagramme und ER-Diagramme.
Entitäten haben keine Methoden
Attribute von Entitäten können nur atomar sein
Vererbung wird bei ER durch is-a-Beziehung realisiert
Aggregation wird bei ER durch part-of -Beziehung realisiert
3.2.6
Gibt es bei Klassendiagrammen auch so etwas wie schwache Entitäten?
Schwache Entitäten werden in UML durch Komposition dargestellt. Komposition ist eine strenge Form
der Aggregation. Dargestellt wird sie durch eine Linie mit einer ausgefüllten Raute am Ende.
3.3
Ermittlung der Anforderungen (Requirements Elicitation)
3.3.1
Was sind Use Cases?
Ein Use Case (Anwendungsfall) beschreibt eine Menge von Aktivitäten eines Systems aus der Sicht seiner
Akteure, die für die Akteure zu einem wahrnehmbaren Ergebnis führen. Ein Anwendungsfall wird stets
durch einen Akteur initiiert. Ein Anwendungsfall ist eine komplette, unteilbare Beschreibung.
3.3.2
Was sind nicht-funktionale Anforderungen an die Software?
Nicht-funktionale Anforderungen beschreiben für den Benutzer wahrnehmbare Aspekte des Systems,
die nicht direkt mit dem funktionalen Verhalten des Systems zusammenhängen. Beispiele sind:
Performance
Reaktionszeit
3.4
Analyse
3.4.1
Wie identifiziere ich Use Cases mit Objekten?
Eine Möglichkeit Objekte zu identifizieren ist Natural Language Analysis. Man analysiert die natürlich
sprachliche Beschreibung der Use Cases. Dabei kann man nach der Heuristik von Abbott vorgehen. Sie
schlägt z. B. folgende Identifikationsregel vor
Eigenname → Objekt
Substantiv → Klasse
Verb → Operation
Auxialverb
...
sein → Vererbung
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
31
Kapitel 3. Software Engineering
3.5
Grobentwurf (System Design)
3.5.1
Was ist eine Software-Architektur?
Eine Software-Architektur ist die Aufteilung eines Softwaresystems in seine Subsysteme, deren Schnittstellen, die Prozesse und Abhängigkeiten zwischen ihnen, sowie den benötigten Ressourcen. Es ist
sozusagen ein Blick aus der Vogelperspektive auf das ganze System.
3.5.2
Wie kann man eine Software-Architektur beschreiben?
Eine Software-Architektur lässt sich z. B. mit dem 4+1 View Model von Kruchten beschreiben. Diese
Modell teilt die Beschreibung in 5 Sichten auf:
Logical View : Das Objekt-Modell der Architektur (Grobentwurf).
Development View : Diese Sicht bezieht sich auf die tatsächliche Zerlegung des Systems in einzelne
Softwaremodule, d. h. die konkrete(n) Zielmaschine(n) werden in diese Betrachtung mit aufgenommen.
Process View : Zeigt Nebenläufigkeits- und Synchronisationsaspekte des Systems.
Physical View : Beschreibt die Zuordnung von Software auf die Hardware. Deployment View wäre
vielleicht ein treffenderer Name.
Scenarios: Die Scenarios beziehen sich auf alle Sichten und beschreiben typische Anwendungsfälle
des Systems.
3.5.3
Wie kann man Systeme unterteilen?
In Subsysteme.
3.5.4
Was ist eine ACL?
Eine Access Control List ist mit einem Objekt verknüpft und enthält 2-Tupel (actor, operation) und
ordnet damit jedem Benutzer Zugriffsrechte zu. Bei jedem Zugriff wird überprüft, ob der Benutzer für
die Operation die entsprechenden Rechte hat. Anschaulich entspricht dies der Gästeliste für eine Party.
3.5.5
Was sind Capabilities?
Eine Capability verbindet einen Akteur mit einem 2-Tupel (class, operation). Die Zugriffsinformation
wird hier bei den Akteuren gespeichert. Anschaulich entspricht dies einer Party mit Einladungen.
3.5.6
Welche Phasen hat das System Design?
Teilaufgaben des System Designs sind:
Festlegung der Designziele
Zerlegung in Subsysteme
Zuordnung von Software auf Hardwarekomponenten
Datenmanagement
Zugriffskontrollmechanismen
Kontrollfluss. Welche Folgen von Operationen werden durchlaufen? Ist das System Event-Abhängig?
Boundary Conditions. Start- und Stopp des System, Fehlerbehandlung.
3.5.7
Neben der Trennung von Komponenten gibt es auch Trennung der Schichten, wozu?
Reduzierung der Komplexität und Austauschbarkeit.
32
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
3.6. Feinentwurf (Object Design)
3.6
Feinentwurf (Object Design)
3.6.1
Erklären Sie Specification und Implementation Inheritance.
Wenn Vererbung nur eingesetzt wird um Code mehrfach zu verwenden, so spricht man von Implementation Inheritance. Wenn Vererbung eingesetzt wird, um durch die Klassen-Subklassen-Hierarchie logisch
zu gliedern, spricht man von Specification Inheritance. Implementation Inheritance sollte möglichst
vermieden werden, sie kann in vielen Fällen besser durch Delegation ersetzt werden.
3.7
Testen
3.7.1
Was ist ein Regressionstest?
Bei jeder Änderung werden alle vorhergehenden Tests wiederholt.
3.7.2
Welche Testverfahren gibt es?
Testverfahren lassen sich wie folgt kategorisieren:
Unit Testing. Beim Unit Testing werden einzelne Komponenten des Systems getrennt getestet, man
unterscheidet zwischen
Blackbox Testing. Beim Blackbox Testen testet man Komponenten nur bzgl. ihrer Ein-/Ausgaben.
Die Implementierung der Komponenten wird nicht betrachtet. Vorgehensweisen sind:
Equivalence Testing. Alle möglichen Eingabe werden in Klassen aufgeteilt. Aus jeder Klasse
wird ein Repräsentant ausgewählt mit dem getestet wird. Man geht nun davon aus, dass sich
die Komponenten für alle Mitglieder einer Klasse gleich verhält. Für jede Äquivalenzklasse
sollten zwei Werte ausgewählt werden, eine typische Eingabe und eine ungültige damit das
Fehlerverhalten der Komponente getestet werden kann.
Boundary Testing. Boundary Testing is ein Spezialfall von Equivalence Testing. Hier wählt
man die Repräsentanten immer so, dass sie an der Grenze zwischen zwei Äquivalenzklassen
liegen. Die Idee dabei ist, dass Programmierer Spezialfälle oft stiefmütterlich behandeln.
Whitebox Testing. Beim Whitebox Testen schaut man sozusagen in die Komponenten hinein
und überprüft deren Implementierung. Eine Möglichkeit ist:
Path Testing. Das Path Testing erfordert genaue Kenntnis des Codes der Komponente.
Zuerst muss man einen Flussgraphen für die Komponente erstellen, dieser Graph beinhaltet
Codeblöcke und Entscheidungen. Dieser kann z. B. als UML Aktivitätsdiagramm dargestellt
werden. Jetzt wählt man die Testeingabe so, dass jede Transition des Diagramms mindestens
einmal schalten muss. Dies ist aber natürlich immer noch kein Beweis für die Korrektheit,
deckt aber normalerweise die meisten Fehler auf. Bei objektorientierten Sprachen wird PathTesting durch Polymorphie und die kürze der Methoden erschwert.
State-based Testing. State-based Testing ist eine zustandsorientierte Testmethode speziell für
objektorientierte Systeme.
Integration Testing. Nachdem die Komponenten einzeln getestet wurden, muss das Zusammenspiel
der Komponenten getestet werden. Dabei gibt es wieder verschiedene Ansätze:
Big-bang Testing. Alle Komponenten wurden zuvor getestet und werden jetzt auf einen Schlag
zusammen gesetzt. Der Vorteil ist, dass man keine zusätzlichen Testumgebungen braucht, der
Nachteil das die Fehlersuche sehr aufwendig ist.
Bottom-Up Testing. Bei einem schichtenorientierten System werden zuerst nur die Komponenten
der untersten Schicht zusammengesetzt und getestet, dann die der nächst höheren usw. Auch
hier braucht man keine Testumgebungen.
Top-Down Testing. Beim Top-Down Testen geht man genau anders herum vor. Der Nachteil
ist, dass man Testumgebungen braucht, die die unteren Schichten simulieren. Der Vorteil ist,
dass man mit dem Test des User Interfaces anfängt.
Sandwich Testing. Beim Sandwich Testing geht man gleichzeitig von oben und unten vor.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
33
Kapitel 3. Software Engineering
System Testing. Mit Unit und Integration Testing sucht man Fehler in einzelnen Komponenten und
im Zusammenspiel der Komponenten. Nach der Integration testet man mit dem System Testing,
ob das System den funktionalen und nicht-funktionalen Anforderungen entspricht.
Functional Testing. Das Functional Testing dient der Überprüfung der funktionalen Anforderungen, die im RAD beschrieben sind. Man hält sich an die beschriebenen Use Cases und geht
ähnlich wie beim Equivalence oder Boundary Testing vor.
Performance Testing. Performance Testing testet das System auf nicht-funktionale Anforderungen, beschrieben in SDD und RAD. Man unterscheidet zwischen:
Stress Testing. Testet ob das System mit auf viele gleichzeitige Anfragen korrekt reagiert.
Volume Testing. Testest ob das System mit grossen Datenmengen zurecht kommt.
Security Testing. Testet die Sicherheit des Systems. Eingesetzt werden Tiger Teams die
Versuchen in das System einzubrechen.
Timing Testing. Test ob die Reaktionszeitanforderungen eingehalten werden.
Recovery Testing. Testet ob sich das System wie gewünscht von Fehlern erholt.
Pilot Testing. Beim Pilot oder Field Testing testen eine ausgewählte Gruppe von Benutzer das
System ohne dass ihnen bestimmte Testscenarios vorgegeben werden. Man unterscheidet:
Alpha Testing. Pilot Test in der Umgebung der Entwicklung.
Beta Testing. Pilot Test in der tatsächlichen Zielumgebung.
Acceptance Testing. Der Kunde testet ob das System den Anforderungen entspricht. Man
unterscheidet:
Benchmark Testing. Der Kunde wählt eine Testmenge mit der System getestet wird. Dies
kann entweder durch echte Benutzer oder spezielle Test Teams erfolgen.
Competitor Testing. Das System wird mit Konkurrenzsystem oder bei Reengineering Projekten mit dem alten System verglichen.
Shadow Testing. Das alte und das neue System laufen parallel und die Resultate werden
verglichen.
Installation Testing. Das System wird in der Zielumgebung installiert und nochmal getestet.
Dabei werden viele Test des Functional und Performance Testings wiederholt. Bestimmte Funktionalität die von anderen System des Kunden abhängig ist, kann erst jetzt wirklich getestet
werden.
3.7.3
Wie viel Aufwand entfällt für das Testen?
Ca. 40%–50%.
3.7.4
Was versteht man unter Black-Box-Testen?
siehe 3.7.2.
3.7.5
Was ist ein Review?
Unter einem Review versteht man die
Man unterscheidet:
händische Analyse des System ohne dieses laufen zu lassen.
Walkthrough. Der Entwickler stellt die API, den Code und die Dokumentation dem Review Team
vor. Das Team analysiert die Abbildung von der Analyse und des Object Design auf Code bzgl.
der Use Cases aus der Analyse Phase und macht entsprechende Vorschläge.
Inspection. Bei der Inspection stellt der Entwickler die API dem Review Team vor, er darf aber
weder Modelle, Code, Dokumentation, o. ä. vorstellen. Das Review Team prüft dann Code, Dokumentation und auch Kommentare im Code. Diese alles geschieht ohne den Entwickler, der nur bei
Unklarheiten herangezogen wird.
Code Reviews sind sehr effektiv, so dass in Experiment bis 60%–85% der Fehler gefunden wurden. Sie
sind aber auch sehr aufwendig.
34
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
3.8. Projektmanagement
3.7.6
Wie geht man bei Verifikation vor?
Verifikation ist der Beweis der Korrektheit eines Programms. Diese ist nur in bestimmten, kleine Fällen
möglich.
3.7.7
Testet man in der Analyse Phase?
Ja. Man kann Prototypen entwickeln und diese Testen.
3.7.8
Wann testet man?
In allen Phasen, aber hauptsächlich während der Implementierung.
3.7.9
Was ist ein Integrationstest?
siehe 3.7.2.
3.8
Projektmanagement
3.8.1
Wie kann man ein Projekt aufteilen?
Man kann ein Projekt in Aktivitäten aufteilen, die wiederum in Tasks aufgeteilt werden. Jeder Task
produziert eine Reihe von Work Products und benötigt eine bestimmte Menge an Ressourcen.
3.8.2
Was versteht man unter Aufwandsschätzung?
Man möchte am Beginn des Projektes den Aufwand den Projektes schätzen. Z. B. in Zeilen von Code
oder Anzahl der benötigten Entwickler.
3.8.3
Wie ist der Einfluss der Projektdauer auf die Kosten?
Bis zu einem gewissen Punkt (z. B. Deadline) ist der Einfluss der Dauer auf die Kosten proportional.
3.8.4
Beschreiben Sie das Cocomo-Modell.
In Abschätzung mit dem Cocomo-Modell läuft in etwa wie folgt ab.
1. Komplexität mit Hilfe des Function-Point-Modells bestimmen. Als Ergebnis erhält die man geschätzte
Anzahl Codezeilen in KLOC.
2. Einteilung des Systems in eine drei Klassen Organic (einfach), semi-detached (mittel) und embedded
(komplex).
3. Entsprechend der Komplexitätsklasse wird nun aufgrund der Anzahl der Codezeilen der Personalaufwand (Personal Effort) in MM (Man-Month) berechnet.
einfach:
mittel:
komplex:
PE = 2.4 · KLOC1.05
PE = 3.0 · KLOC1.12
PE = 3.6 · KLOC1.20
4. Anhand dieses Wertes kann nun die Entwicklungszeit in Monaten bestimmt werden:
einfach:
mittel:
komplex:
TDEV = 2.5 · PE0.38
TDEV = 2.5 · PE0.35
TDEV = 2.5 · PE0.32
5. Um die Anzahl der Entwickler N zu bestimmen:
N=
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
PE
TDEV
35
Kapitel 3. Software Engineering
Zum Beispiel gilt für ein Projekt mittlerer Komplexität mit geschätzten 30000 Zeilen Code.
PE
3.0 · 301.12
=
≈
135 MM
Damit
TDEV
=
≈
2.5 · 1350.35
14 M
Für die Anzahl der Entwickler ergibt sich.
N=
135
≈ 10
14
Man könnte das System also in 14 Monaten mit 10 Programmierern entwickeln.
3.9
Vorgehensmodelle
3.9.1
Was ist das V-Modell?
Das V-Modell ist eine Erweiterung des Wasserfallmodells. Es enthält direkte Verbindungen zwischen
Entwicklungs- und Verifikationsphasen.
36
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
3.9. Vorgehensmodelle
3.9.2
Was ist das Spiralmodell?
Auch die Weiterentwicklung des Wasserfallmodells durch das flexiblere Spiralmodell bietet benannte
und standardisierte Entwicklungsschritte. Diese werden jedoch in einem zyklischen Prozess mehrfach
durchlaufen. Das Spiralmodell trägt der Schwierigkeit Rechnung, Anforderungen vorweg zu ermitteln
und berücksichtigt den Lernprozess bei der Entwicklung. Ziel ist aber nach wie vor ein fertiges Produkt.
Versionen gibt es nur während der Entwicklung. Das wichtigste am Spiralmodell ist, dass es risk-driven
ist.
Festlegen der Ziele,
Lösungsvorschläge,
Nebenbedingungen
und Einschränkungen
Risikoanalye
Erarbeitung und Beurteilung
von Lösungsvorschlägen,
Erkennen und Beseitigen
von Risiken
Risikoanalye
Risikoanalye
fo
w urf
e
alys
ent
rd
ob
An
Entwickulungs- Validierung
plan der Analyse
Validierung
Integrations- und Verfikation
plan des Entwurfs
Acceptance
Test
Planung der
nächsten Phase
Feinentwurf
Gr
er
Anforderungsplan
Prototyp 2 Prototyp 3 Prototyp 4
An
un
gen
Prototyp 1
Code
Integration
& System
Test
Entwicklung und
Validierung des
Produkts der nächsten Stufe
Jede Runde beinhaltet folgende Aktivitäten.
Phase 1
Ziele und Bedingungen festlegen
Lösungen vorschlagen
Phase 2
Risiken erkennen
Risiken beheben
Phase 3
Produkt für nächste Runde entwickeln. . .
und testen
Phase 4
nächste Phase planen
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
37
Kapitel 3. Software Engineering
3.9.3
Gibt es bessere Vorgehensmodelle?
Es gibt die zyklische Modelle die immer neue Generationen der Software entwickeln, ein Beispiel ist
RUP:
Beim Rational Unified Process besteht die Entwicklung aus mehreren Zyklen, am Ende eines jeden
Zyklus wird dem Kunden ein Produkt geliefert. Jeder dieser Zyklen besteht aus vier Phasen, wobei
jede Phase wiederum in 9 Workflows zerlegt ist. Dadurch wird die Entwicklung sozusagen in zwei
Dimension aufgeteilt. Die Phasen:
Inception. Hier werden Use Case entdeckt und beschrieben, Risiken und Ressourcenverbrauch
abgeschätzt.
Elaboration. Die Ideen werden konkretisiert, ein Architekturprototyp aufgestellt und getestet. Dies
ist die wichtigste Phase.
Construction. In diese Phase finden die Entwicklungsprozesse statt.
Transition. In diese Phase fällt die Installation.
3.9.4
Was ist ein Vorgehensmodell und welche kennen Sie?
Vorgehensmodelle dienen zur Benennung und Ordnung von produktbezogenen Tätigkeiten bei der Softwareentwicklung. Beispiele sind:
Wasserfallmodell
V-Modell
Spiralmodell
RUP
Dvorak-Modell
3.9.5
Welche Kritik gibt es am Wasserfallmodell?
Im ürsprünglichen Wasserfallmodell werden die Phasen streng sequentiell durchlaufen. Dies entspricht
nicht der Realität bei einem Softwareprojekt. Das wird schon daran klar, dass der Wissenserwerb nicht
linear abläuft. Eine einzelne Information, auch sehr spät im Entwicklungsprozess, kann alles über den
Haufen werfen . Das Wasserfallmodell ist dokumentgesteuert.
Anforderungsermittlung
Analyse
Grobentwurf
Feinentwurf
Implementierung
Test
Einsatz und
Wartung
3.9.6
38
Vergleichen Sie das Wasserfallmodell mit dem Spiralmodell.
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
3.9. Vorgehensmodelle
Jede Runde des Spiralmodells entspricht einer Phase des Wasserfallmodells. Es ermöglicht es flexibler
auf Änderungen zu reagieren. Der wichtigste Unterschied zwischen den Modell ist, dass das Spiralmodell
risikogesteuert ist.
3.9.7
Steckt in jedem Spiralmodell ein V-Modell?
Ja.
3.9.8
Zeichen Sie ein V-Modell auf.
Client
Acceptance
Test
Anforderungsermittlung
System
Test
Analyse
Integration
Test
Grobentwurf
Unit
Test
Feinentwurf
Implementation
3.9.9
Erklären Sie das Dvorak-Modell.
Das Dvorak-Modell erhöht die Flexibilität in dem es in der Entwicklungsphase beliebige Zwischenschritte
zulässt.
Client
Acceptance
Test
...
...
...
System
Test
...
Integration
Test
Anforderungsermittlung
Analyse
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
Grobentwurf
Feinentwurf
Implementation
Unit
Test
39
Kapitel 4
Objektorientierung
4.1
Allgemeines
4.1.1
Erklären Sie die Merkmale und Konzepte der Objektorientierung.
OO Sprachen
Kapselung von Daten
Instantiierung von Klassen
Vererbung
Polymorphie
OO Systemmodellierung
Analyse und Design mit OO Beschreibungstechniken
Visualisierung einer Abstraktion des Systems
Statische und dynamische Sichten
4.1.2
Was ist Polymorphie?
Polymorphie ist die Eigenschaft einer Variable für Objekte verschiedener Klassen stehen zu können.
4.1.3
Was gibt es für Arten von Polymorphie?
Ad-hoc Polymorphie. Überladen von Operatoren.
Strukturelle Polymorphie. Ein Variable kann für Objekte verschiedener Klassen stehen, wenn sie
eine gemeinsame Oberklasse haben.
Parametrische Polymorphie. Wird zum Beispiel bei parametrischen Klassen verwendet.
4.1.4
Was sind Vorteile der Polymorphie?
Vereinfacht die Programmierung.
4.1.5
Was sind Nachteile der Polymorphie?
Polymorphie muss oft durch dynamisches Binden gelöst werden, das geht auf die Performance. Oft
wird schlechtere Lesbarkeit des Codes als Nachteil angegeben. Das ist Blödsinn. Wenn man statt
Polymorphie haufenweise verschachtelte Instance-Of-Abfragen verwendet, wird der Code sicher nicht
besser lesbar.
4.1.6
Was gibt es für Notationen?
Booch-Notation und UML.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
41
Kapitel 4. Objektorientierung
4.2
Entwurfsmuster
4.2.1
Was sind Entwurfsmuster?
Softwareentwickler haben bei der Analyse grosser Softwaresysteme festgestellt, dass es für ähnliche Problemstellungen gleiche Konfigurationen von Entwurfskomponenten gefunden wurden, d. h. Klassen oder
Objekte die eine bestimmte Dienstleistung erbringen. Solche Lösungen lassen sich als Muster beschreiben und benennen und bilden damit die Grundlage für Sammlungen zugehöriger Musterbeschreibungen.
4.2.2
Erklären Sie das Decorator-Pattern.
Das Decorator-Pattern erlaubt es die Funktionalität von Objekten zur Laufzeit zu erweitern. Es bietet
oft eine flexible Alternative zur Vererbung.
4.2.3
Erklären Sie das Observer-Pattern.
Mit dem Observer-Pattern kann eine 1:N Beziehung zwischen Objekten realisiert werden, so dass die
N Objekte (Observer) geupdatet werden, wenn das eine Objekt (Subject) seinen Zustand ändert. Dies
wird z. B. bei MVC eingesetzt. Bei Java Swing heissen die Observer Listener.
4.2.4
Erklären Sie das Adapter Pattern.
Eine Adapterklasse kann man eine andere Klasse
Schnittstelle hat.
4.2.5
vorschalten, wenn diese nicht die gewünschte
Erklären Sie das Facade Pattern.
Mit dem Facade Pattern kann man den Zugriff aus ein ganzes Subsystem vereinfachen. Dem Subsystem
wird eine Facade-Klasse hinzugefügt, die die ganze Kommunikation mit anderen Subsystemen abwickelt.
4.2.6
Erklären Sie das Bridge Pattern.
Mit dem Bridge-Pattern kann die Implementierung und die Abstraktion einer Klasse in zwei unterschiedliche Klassenhierarchien aufgeteilt werden. Dadurch können die beiden unabhängig voneinander
geändert werden.
4.2.7
Erklären Sie das Strategy Pattern.
Mit dem Strategy Pattern lassen sich einzelne Algorithmen einer Klasse getrennt austauschen. So kann
man z. B. in eine Klasse die Graphen darstellt verschiedene Layoutalgorithmen einhängen.
4.2.8
Erklären Sie das Visitor Pattern.
Mit dem Visitor-Pattern können Operationen auf Klassen selbst wieder in Klassen gepackt werden.
Dadurch können Operationen für Klassen definiert werden ohne das die Klassen selbst geändert werden
müssen. Das ist speziell bei generierten Klassen interessant. Das Visitor-Pattern wird häufig bei der
semantischen Analysephase im Compilerbau eingesetzt.
4.2.9
Erklären Sie das Command Pattern.
Das Command Pattern ist ein objektorientierter Ersatz für Call-Back-Methode. Es erlaubt einzelne
Operationen dynamisch in Objekte einzuhängen. Das Actionkonzept von Java Swing ist eine Anwendung des Command Patterns.
42
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
Literaturverzeichnis
[Aho et al., 1986]
Aho, Alfred V. et al. Compilers: Principles, Techniques and Tools. AddisonWesley, 1986
[Duden Informatik, 1993]
Duden Informatik. 2. Aufl. Dudenverlag, 1993
[Bauer & Höllerer, 1998]
Bauer, Bernhard; Höllerer Riitta. Übersetzung objektorientierter Programmiersprachen. Springer-Verlag, 1998
[Bruegge & Dutoit, 2000]
Buegge, Bernd; Dutoit, Allen H. Object-Oriented Software Engineering: Conquering Complex and Changing Systems. Prentice Hall, 2000
[Gamma et al., 1994]
Gamma, Erich et al. Desgin Patterns: Elements of Reusable Object-Oriented
Software. Addison-Wesley, 1994
[Oestereich, 2001]
Oestereich, Bernd Die UML-Kurzreferenz für die Praxis. Oldenbourg, 2001
[Kemper & Eickler, 1999]
Kemper, Alfons; Eickler, André Datenbanksystem: Eine Einführung. Oldenbourg, 1999
[Rechenberg & Pomberger, 1999] Rechenberg, Peter; Pomberger, Gustav (hrsg.) Informatik-Handbuch. 2. Aufl.
Hanser, 1999
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
43
Teil II
Technische Informatik
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
45
Kapitel 5
Rechnerarchitektur
5.1
Allgemeines
5.1.1
Erläutern Sie das von-Neumann-Konzept.
Beim von-Neumann-Konzept gelten folgende Prinzipien:
1. Der Computer besteht aus
Speicher
Rechenwerk
Leitwerk
Ein-/Ausgabegeräten.
Heute:
Aufspaltung des Speichers in Speicherhierarchie
Leitwerk und Rechenwerk formen Zentraleinheit
gelegentliche mehrere Rechenwerke im Zentralprozessor
Ein-/Ausgabegeräte über Gerätesteuerungen indirekt angeschlossen
Verbindungsnetz ist kritischer Teil
2. Die Struktur des Rechners ist unabhängig vom bearbeiteten Problem.
Heute: gilt immer noch.
3. Programm und Daten stehen im selben Speicher und können beide durch die Maschine verändert
werden.
Heute: Manchmal liegt das Programm in einem Festspeicher, z. B. bei Taschenrechnern, aber in Normalfall wie von-Neumann, aber getrennt in unveränderliche Teile (pure segments) und veränderliche
Teile (impure segments). Die Möglichkeiten der Veränderung des Programms wurde durch Sprünge
und Adressmodifikation abgelöst. Das ist sicherer und erlaubt Programme als pure segments.
4. Der Speicher ist Zellen gleicher Grösse geteilt, die durch fortlaufende Nummern bezeichnet sind.
Heute: Gilt noch immer, aber die untypisierten, unstrukturierten Zellen sind Hauptangriffspunkt
von von-Neumann-Kritikern.
5. Das Programm besteht aus einer Folge von Befehlen, die sequentielle Aufträge beschreiben und in
der Aufzeichnungsreihenfolge auszuführen sind. Die Befehle enthalten i. A. nicht die Werte, mit
denen gerechnet werden soll, sondern die Adresse der Zellen, wo die Werte liegen.
Heute: Heutige Prozessoren bemühen sich mit allen möglichen Tricks (Pipelining, look-aheadMechanismen, mehrere Rechenwerke) die Sequentialität zu umgehen. Trotzdem muss das Ergebnis
dem der sequentiellen Verarbeitung entsprechen.
6. Von der Folge kann durch Sprungbefehle abgewichen werden. Die Ausführung eines Sprungs kann
von errechneten Werten abhängig gemacht werden. Heute: praktisch unverändert.
7. Die Maschine benutzt Binärcodes, Zahlen werden dual dargestellt. Heute: praktisch unverändert.
Abbildung zeigt original von-Neumann-Modell:
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
47
Kapitel 5. Rechnerarchitektur
Befehle (Programme)
Hauptspeicher
Rechenwerk
Daten
Programm
Daten
Leitwerk
BZ
IR
SR
AC
Adressen
Daten
E/A-Werk
5.1.2
Welche von-Neumann-Einheiten kommunizieren heutzutage miteinander und wie?
Der Prozessor ist über den Prozessor-Speicher-Bus mit dem Hauptspeicher verbunden. Auch mit den
Peripheriegeräten kommuniziert er über Busse. Die Abbildung zeigt eine typische Bushierarchie.
Prozessor
Secondary
Cache
Hauptspeicher
E/ASteuerung
für langsame
Geräte, z.B.
Bänder
Peripheriebus
Prozessor-Speicher-Bus
Bussteuerung
Busbrücke
für schnelle
Geräte, z.B.
LAN
E/ASchnittstelle
Systembus
5.1.3
Wie erweitern heutige Architekturen das von-Neumann-Konzept?
Adressmodifikation: die Programmadresse wird zuerst in eine Prozessadresse und dann in eine
Maschinenadresse umgesetzt.
Gleichzeitige Bearbeitung in mehreren weitgehend unabhängigen Werken: Zentralprozessoren, Rechenwerke, Kanäle, Peripheriegeräte,. . .
Automatisch verwaltete Speicherhierarchie.
Steuerung nicht durch ein Programm sondern eine Hierarchie von Steuervorgängen.
Programmunterbrechung durch interne und externe Signale.
5.1.4
Was für Klassifikationssyteme kennen Sie?
1. Klassifikationssystem von Flynn, klassifiziert nach:
SI vs MI : ein oder mehrere (durch die Rechnerhardware) gleichzeitige Progamminterpretationen
SD vs MD: ein oder mehrere (durch die Rechnerhardware) gleichzeitige Operationen auf Daten
Dadurch ergeben sich Kombinationen wie SISD (Standard), SIMD (Vektor-/Feldrechner), MIMD
(Multiprozessoren)
48
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.1. Allgemeines
2. Erlangen Classification System (ECS): Rechner werden durch Tripel von Paaren beschrieben
(k ∗ k 0 , d∗ d0 , w∗ w0 ).
Kollateralität der Programminterpretation:
k Zahl der Leitwerke bzw. Prozessoren
k 0 Zahl der (hardwareunterstützt) im Pipelining zusammen wirkenden Programminterpretationen
Kollateralität der Befehlsausführungen je Programminterpretation:
d Zahl der gleichen Rechenwerke je CPU
d0 Zahl der verschiedenen Rechenwerke je CPU
Kollateralität in Ausführung eines Befehls
w Operandenwortlänge
w0 Zahl der Pipelinestufen
Beispiele:
Intel 8085
Multirechner aus 128 Intel 80386
Cray.1 Vektorrechner
5.1.5
(1∗ 1, 1∗ 1, 8∗ 1)
(128∗ 1, 1∗ 1, 32∗ 1)
(1∗ 1, 1∗ 12, 64∗ 14)
Was ist SPEC?
Die Standard Performance Evaluation Corporation (SPEC) unterhält als Dachorganisation diverse Unterabteilungen, die sich mit Grafik (GPC) oder High Performance Computing (HPC) beschäftigen und
nicht zuletzt gibt es die Open System Group OSG, die für Komponenten und Systeme im Workstationund Multiuser-Serverbetrieb zuständig ist. Diese OSG hat diverse Benchmarks entwickelt beziehungsweise zusammengestellt, zum Beispiel für Web-Server (SPEC WEB99), Mail-Server (SPEC MAIL2001),
Java Virtual Maschines (SPEC JVM98), Java Business (SPEC JBB2000) – aber am bekanntesten ist
ihre CPU-Benchmark-Suite SPEC CPU2000.
Aber nicht nur in der multikulturellen Zusammensetzung des Benchmark-Komitees, sondern auch in
vielen anderen Punkten unterscheidet sich der CPU2000-Benchmark der SPEC von normalen Benchmarks. Insbesondere liegt die Suite als Source (C, C++, Fortran) vor, sodass man weiß, was der Benchmark so treibt und es der Tester durch die Wahl der Compiler und Optimierungsflags in der Hand hat,
ob der Benchmark mehr altbacken arbeiten oder das Potenzial der modernen Prozessoren mit all
ihren neuen Funktionseinheiten voll ausschöpfen soll.
Die Suite besteht aus zwei Teilen, dem Gleitkommabereich (SPECfp), der eine Fülle wissenschaftlicher Software umfasst und überwiegend in Fortran kodiert ist, und dem Integer-dominierten Bereich
(SPECint), kodiert in C/C++. SPECint enthält auch viele typische Desktop-Aufgaben, etwa Komprimierung (gzip und bzip2), Kompilation mit gcc, auch ein Schachspiel (crafty) oder Sprachanalyse
(parser). SPECint spiegelt damit wesentlich mehr die normale Desktop-Anforderung wider und eignet
sich daher eher für ein Speed rating von Desktop-Prozessoren. Das gleiche gilt für Server, für die
Gleitkommaleistung eher nebensächlich ist. Auch hier zählt vor allem der SPECint-Wert.
Zwei verschiedene Messverfahren erlaubt die SPEC in ihren restriktiven Runrules. Bei Base muss
jede der beiden Einzelsuites mit einem Compiler und einem gemeinsamen Satz von höchstens vier
Optimierungsflags verwendet werden, bei Peak darf man für jedes einzelne der insgesamt 26 Programme
unterschiedliche Compiler mit beliebigen Flags mischen.
Diese Zusammenfassung stammt aus der c’t 21/01.
Für jeden der einzelnen Test, 12 bei SPECint und 14 bei SPECfp, wird der sog. SPEC-Ratio berechnet.
Der SPEC-Ratio ist der Kehrwert der Laufzeit geteilt durch den Kehrwert einer Referenzlaufzeit. Aus
den SPEC-Ratio-Werte wird dann mit dem geometrischen Mittel ein Mittelwert bestimmt, der SPECMark.
5.1.6
Kennen Sie noch andere Rechner ausser Workstations?
Taschenrechner
PDAs
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
49
Kapitel 5. Rechnerarchitektur
Spielkonsolen
PCs und Laptops
Servers
Mainframes
Supercomputer
5.1.7
Welche Bedeutung haben Angaben wie SPEC-Werte, MIPS oder MFLOPS?
MIPS (Million Instructions per Second ) und FLOPS (Million Floating Point Operations per Second )
sind Durchsatzkenngrössen. SPEC-Werte sind die Ergebnisse der standardisierten SPEC-Benchmarks.
MIPS- und FLOPS-Werte werden häufig falsch interpretiert. Vergleiche zwischen Rechnern aufgrund
dieser Werte sind irreführend, wenn diese unterschiedliche Befehlssätze oder Hardwareunterstützung für
Gleitpunktoperationen haben. Eine RISC-System hat meist einen höheren MIPS-Wert als ein CISCWert, das sagt aber noch überhaupt nichts aus, da die Mächtigkeit der Befehle sehr unterschiedlich ist.
Ein weiteres Problem ist, dass die Werte insofern keine verlässlichen Aussagen machen, da sich moderne
Prozessoren sich in wirklichen Einsatz die meiste Zeit mit Pipelinekonflikten und dem Warten auf den
Speicher beschäftigen und nicht mit Gleitpunktberechnungen.
SPEC-Werte haben einen eine deutlich höhere Aussagekraft, da durch Standardisierung und Mittelung
das erste Problem beseitigt ist. Rechensysteme lassen sich damit tatsächlich vergleichen. Aber nur bzgl.
ihrer SPEC-Werte. Der SPEC-Benchmark ist synthetisch und es ist nicht gesagt, dass die erzielten
Werten etwas über die Leistungsfähigkeit eines Systems bei seiner realen Aufgabe aussagen.
5.1.8
Was kann man bei Rechnern bewerten und was für Methoden gibt es dafür?
Die bei Rechnern zu bewertenden Kenngrössen lassen sich in drei Bereich aufteilen.
Zeit. Die Verweilzeit ist die Zeit, die ein Auftrag insgesamt im System verbringt. Die Verweilzeit
setzt sich zusammen aus Wartezeit und Bedienzeit. Die Verweilzeit wird auch als Verzögerung,
Antwortzeit oder Latenz bezeichnet. Die Zeiten sind meist stochastische Grössen, im Allgemeinen
interessiert aber nur der Erwartungswert. Beispiele sind: Befehlsausführungszeit (CPI), Speicherzugriffszeit, Laufzeit eines Programmes, Verzögerung einer Nachricht in einem Netz.
Durchsatz. Der Durchsatz ist definiert als die Anzahl der pro Zeiteinheiten bedienten Aufträge.
Der maximale Durchsatz heisst Grenzdurchsatz. In den meisten Fällen sind die Antwortzeiten für
System, die in der Nähe des Grenzdurchsatzes operieren, sehr hoch. Deshalb interessiert meist der
maximal erzielbare Durchsatz, so dass eine obere Schranke für die Verweilzeit nicht überschritten
wird. Das nennt man Usable Capacity. Die Verlustrate ist die Anzahl von Aufträgen, die pro
Zeiteinheit verloren geht. Beispiele sind: MIPS und FLOPS eines Prozessors, Bit/s auf einem Bus
oder Netz, ausgeführte Jobs pro Stunde, Zellverlustrate bei ATM.
Auslastung. Unter der Auslastung eines System versteht man das Verhältnis von tatsächlich erreichtem Durchsatz zum Grenzdurchsatz, dies wird manchmal auch als Effizienz bezeichnet. Bei
einem zusammengesetzten System, stellt das System mit der höchsten Auslastung den Bottleneck
dar.
Zur Bewertung der obigen Kenngrössen bietet es sich an das System als einfaches Warteschlangensystem
zu modellieren. Deshalb gilt auch der Satz von Little:
U = λ · Tr
wobei U die mittlere Anzahl der Aufträge im System, λ die Ankunftsrate und Tr die mittlere Verweilzeit
bezeichnet.
Zur Bestimmung dieser Kenngrössen gibt es verschiedene Verfahren, die sich in drei Gruppen gliedern
lassen.
Analytische Modelle und Verfahren. In analytischen Modellen wird das zu bewertenden System
in Form von Gleichung beschrieben. Verwendet werden einfache Formeln, Warteschlangenmodelle,
Petri-Netze. Speziell bei den Warteschlangenmodellen stehen mächtige Methoden zur Bewertung
zu Verfügung. Generell gilt aber, dass der Entwurf von analytischen Modellen mit zunehmender
Komplexität der Systeme immer schwieriger bis praktisch unmöglich wird.
50
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.1. Allgemeines
Simulation. Bei der Simulation werden Struktur und Verhalten des Systems in einem geeigneten
Abstraktionsgrad mit in einem ausführbaren Rechnermodell nachgebildet. Man unterscheidet zwischen stochastischer und deterministischer Simulation. Bei der stochastischen Simulation werden
die Modelle mit zufälligen Daten gefüttert. Bei der deterministischen Simulation verwendet man
Daten die aus Experimenten mit realen System gewonnen wurden.
Messung. Eine weitere Methode ist, Messungen an existierenden System durchzuführen. Man unterscheidet zwischen Monitoring und Benchmarking. Monitoring dient dazu interessante Ereignisse,
Operationen und Zustände von Systemen aufzuzeichnen. Ziel ist es das Verhalten des Systems zu
verstehen und Engpässe zu identifizieren. Ausserdem können Werte gewonnen werden, die bei den
deterministischen Simulationen eingesetzt werden. Benchmarking wird in 5.1.9 genauer beschrieben.
Validierung. Wichtig ist eine fundierte Validierung der Modelle.
5.1.9
Was ist Benchmarking?
Benchmarks sind standardisierte Messprogramme zur Ermittlung der Rechnerleistung. Es wird nicht
nur die Leistung der Hardware, sondern des Gesamtsystems gemessen. D. h. Compiler und Betriebssystem werden mit bewertet. Es gibt Benchmarks die im Quellcode vorliegen und sog. Paper-and-Pencil Benchmarks. Bei diesen ist nur die Aufgabe spezifiziert, die Lösung muss selbst implementiert werden.
Man unterscheidet zwischen synthetischen und natürlichen Benchmarks.
Synthetische Benchmarks. Man benutzt Bausteine, die jeweils eine gewünschte Teilbelastung erzeugen und im Hinblick auf die Gesamtleistung zu einem Benchmark komponiert werden. Beispiele
sind Whetstone und SPEC (siehe 5.1.5).
Natürliche Benchmarks. Bei natürlichen Benchmarks benutzt man als repräsentativ angesehene
echte Programme zur Leistungsmessung. Beispiele sind Benchmarks die z. B. PCs mit Windows
und typischen Office-Anwendungen testen.
5.1.10
Definieren Sie die Begriffe Zuverlässigkeit und Verfügbarkeit.
Unter der Zuverlässigkeit R(t) versteht man die Wahrscheinlichkeit eine Systems das Zeitintervall [0, t]
zu überleben, unter der Voraussetzung, dass es zum Zeitpunkt t = 0 funktionsfähig war. Da das System
zu Beginn des Zeitintervalls funktionsfähig ist, gilt R(0) = 1. Ausserdem geht man davon aus, dass das
System irgendwann ausfällt.
lim R(t) = 0
t→∞
Die Ausfallrate wird mit λ(t) bezeichnet:
λ(t) = −
dR(t)
/R(t)
dt
Wenn man von einer konstanten Ausfallrate ausgeht, so gilt für die Zuverlässigkeit:
R(t) = e−λt
Die mittlere Zeit bis zu einem Fehler (MTF) berechnet sich dann so:
Z ∞
1
MTF =
R(t) dt =
λ
t=0
Die Annahme, dass λ konstant ist, gilt für technische Systeme im Normalbereich, d. h. Frühausfälle hat
es bereits hinter sich gelassen und Spätausfälle noch nicht erreicht.
Bei der Zuverlässigkeit unterscheidet man nur zwischen den Zuständen läuft (1) und läuft nicht (0).
Bei reparierbaren System interessiert weiterhin der Begriff der Verfügbarkeit. Die Verfügbarkeit A(t)
ist Wahrscheinlichkeit, dass das System zu einem Zeitpunkt t in einem funktionierenden Zustand angetroffen wird. Die stationäre Verfügbarkeit
A = lim A(t)
t→∞
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
51
Kapitel 5. Rechnerarchitektur
gibt den zu erwartenden Bruchteil der Zeit an, den das System zur Verfügung steht. Zum Reparieren des System braucht man eine durchschnittliche Zeit MTR, den Kehrwert davon bezeichnet man
als Reparaturrate und nennt ihn µ. Wenn ein System eine konstante Ausfallrate und eine konstante
Reparaturrate hat, dann gilt für die Verfügbarkeit:
A=
MTF
µ
=
λ+µ
MTR + MTF
5.2
Zentralprozessoren
5.2.1
Wie sieht der Maschinenbefehlszyklus aus?
1. Befehlsholphase (BH ). Nächsten Befehl ins Instruktionsregister laden.
2. Decodierungsphase (DE ). Interpretation des Maschinenbefehls.
3. Operandenholphase (OP ). Den ALUs die Operanden zur Verfügung stellen.
4. Ausführungsphase (AU ). Befehl ausführen.
5. Rückschreibephase (RS ). Ergebnis in Register oder Speicher ablegen.
6. Adressierungsphase (AD). Befehlszähler fort schalten, evtl. Springen.
Der klassische Maschinenbefehlszyklus von RISC-Maschinen sieht so aus:
1. Instruction Fetch. Nächsten Befehl holen und Befehlszähler fort schalten.
2. Instruction decode/register fetch. Befehl dekodieren und Register lesen. Bei Verzweigungsbefehle
kann bereits in dieser Phase das eventuelle Sprungziel bestimmt werden.
3. Execution/effective address. In Abhängigkeit vom Befehl führt die ALU eine der drei Funktionen
aus.
Memory reference. Die ALU berechnet Prozessadresse mit Basisregister und Offset.
Register-Register ALU Instruction. Die ALU führt die entsprechende Berechnung durch, verwendet werden die aus den Register geladenen Wert.
Register-Immediate ALU Instruction. Die ALU führt die entsprechende Berechnung durch.
4. Memory Access. Falls es sich um einen Load/Store-Befehle handelt, wird hier der Speicher geschrieben, bzw. gelesen.
5. Write Back. Ergebnisse der Berechnung oder des Loads werden in die Register zurückgeschrieben.
5.2.2
Was ist der Unterschied zwischen RISC und CISC?
CISC-Architekturen haben folgende Eigenschaften:
Umfangreiche Befehlssätze mit einigen hundert Befehle, die Teilweise komplizierte Aufgaben lösen
viele Adressierungsarten mit Register-, Speicher- und Keller-Zugriffsarten und Adressrechnung in
Maschinenbefehlen
Familienkonzept bei aufwärtskompatiblen Prozessoren mit grossen Leistungsunterschieden
Nutzung von Mikroprogrammierung für das Leitwerk
Trennung von Befehlssatz, Implementierung und Realisierung
Befehlssätze sind möglichst speichersparend entworfen, hauptsächlich durch uneinheitliches Befehlsformat
Im Gegensatz dazu zeichnen sich RISC-Architekturen durch folgende Eigenschaften aus.
elementare, kleine Befehlssätze, deren Operandenhol- und Ausführungsphase in je einem Takt
durchführbar ist
Verzicht auf Adressierungsarten und Adressrechnung in der Operandenholphase
Operanden ausschliesslich in Registern (Load-Store-Architektur ) und grosse, universelle Registersätze
52
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.2. Zentralprozessoren
Nutzung von Pipelining
fest verdrahtete Leitwerke (= keine Mikroprogrammierung)
einheitliches Befehlsformat
Kooperation von optimierenden Compiler und der Prozessorarchitektur zur Leistungssteigerung
5.2.3
Welche Arten von Interrupts gibt es?
Interrupts lassen sich nach vielen Kriterien klassifizieren, z. B. Software vs. Hardware, Maskable vs
Non-Maskable, Precise vs Imprecise.
5.2.4
Wer kann welche Interrupts auslösen?
Kommt auf den Interrupt an.
Arithmetische Interrupts werden vom Rechenwerk ausgelöst
Seitenfehler von der MMU
Hardwareinterrupts z. B. von der Tastatur
...
5.2.5
Was ist Pipelining?
Idee beim Pipelining ist es die Befehle wie am Fliessband abzuarbeiten. Parallelismus in der
Ausführung und damit Leistungssteigerung entsteht beim Pipelining dadurch, dass das erste Teilwerk
nach Bearbeitung des i-ten Befehls bereits mit dem Befehl i + 1 fortfahren kann. Bedingung ist, dass
für alle Phasen des Maschinenzyklusses ein eigenes Werk zur Verfügung steht.
Die Abbildung zeigt eine 6-Stufige Pipeline.
Befehl 1
2
3
4
BH DE OP AU
BH DE OP
BH DE
BH
RS
AU
OP
DE
AD
RS AD
AU RS AD
OP AU RS AD
t
Eine Pipeline kann nur effektiv Arbeiten wenn die einzelnen Phasen des Maschinenzyklus in etwa gleich
lang dauern. Bei modernen Prozessoren unterscheiden sich die Befehle speziell in der Ausführungsphase
oft recht stark, deshalb werden die einzelnen Phasen des Befehlszyklus hier nochmal in mehrere Phasen
zerlegt.
Um jede Phase des Befehlszyklus’ möglichst in einem Takt auszuführen, werden verschiedene Techniken
in den unterschiedlichen Phasen eingesetzt:
1. Befehlsholphase. Die Befehlsholphase kann durch den Einsatz von Caches und weiteren Befehlspuffer
die logisch zwischen Cache und dem Instruktionsregister liegen, beschleunigt werden.
2. Decodierungsphase. Die Beschleunigung der Decodierphase erfolgt hauptsächlich durch Vereinheitlichung und Vereinfachung des Befehlssatzes. Wesentliche Voraussetzung für das einheitliche
Befehlsformat ist die ausschliessliche Verwendung von Registeroperanden. Dadurch müssen bei der
Dekodierung keine aufwendigen Adressberechnungen vorgenommen werden.
3. Operandenholphase. Bei RISC-Architekuren ist die Operandenholphase sehr einfach, da nur Register als Operanden verwendet werden. Weiter Vereinfachung ergibt sich dadurch, dass keine Statusregister verwendet werden. Auch die Verwendung des Dreiadressprinzips hilft, da das überschreiben
von Operanden entfällt. Durch diese und andere Eigenschaften von RISC-Architekturen wird die
Operandenholphase so einfach, dass sie zusammen mit der Decodierphase ausgeführt werden kann.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
53
Kapitel 5. Rechnerarchitektur
4. Ausführungsphase. Zu Beginn der 80er ging man davon aus, dass nur solche Befehle verwendet werden sollten, die in einem Takt auszuführen waren. Aus Leistungsgründen sind aktuelle Prozessoren
von diesem strengen RISC-Prinzip abgewichen. Die Rechenwerke moderner Prozessoren haben
meist mehrer ALUs für bestimmte Anwendungen. Die verschiedenen ALUs dürfen, gesteuert durch
das Leitwerk, mehrer Befehle gleichzeitig ausführen. Man spricht von superskalaren Rechenwerken.
Das Leitwerk muss dafür sorgen, dass die Programmsemantik erhalten bleibt.
5. Rückschreibephase. Auch die Rückschreibephase wird durch das Load/Store-Prinzip beschleunigt.
Es müssen lediglich die von der ALU kommenden Daten in die Register zurückgeschrieben werden.
Bei Store-Befehlen kann es passieren, dass auf den Speicher gewartet werden muss, dies kann durch
den Einsatz von Caches beschleunigt werden. Zusätzlichen können noch Schreibpapier verwendet
werden.
6. Adressierungsphase. In der Adressierungsphase müssen die Befehlszähler für die in den verschiedenen Pipelinestufen steckenden Befehle hochgezählt oder bei Sprungbefehlen entsprechend angepasst
werden.
5.2.6
Was bringt Pipelining?
Pipelining bewirkt eine dramatische Performanceverbesserung. Rein theoretisch gilt:
Zeit pro Befehl mit Pipelining =
Zeit pro Befehl ohne Pipelining
Anzahl der Pipelinestufen
Dies würde gelten, wenn die Stufen perfekt balanciert währen, alle Befehl von einander unabhängig
währen und es keine Sprünge gebe.
5.2.7
Wo wird Pipelining angewendet?
In allen modernen Prozessoren.
5.2.8
Was ist RISC?
siehe 5.2.2.
5.2.9
Warum arbeiten aktuelle Intel-Prozessoren intern wie RISC stellen aber nach aussen CISC-Befehle zur
Verfügung?
Für vernünftige Nutzung des Pipelining-Konzept eignen sich nur RISC-Befehle. Um die Kompatibilität
zu gewährleisten werden die nach aussen durch CISC-Befehle versteckt.
5.2.10
Was ist MMX?
MMX ist die Intel Multimedia Extension. Das sind zusätzliche Prozessorbefehle die der schnelle Verarbeitung von Multimediadaten dienen. Es handelt sich dabei um SIMD-Befehle, wobei ein Befehl einen
ganzen Satz von Daten verändern kann. Für MMX wurden keine neuen Register eingeführt, es werden
64 Bit der 80 Bit FPU-Register verwendet. Daher keine gleichzeitigen FP- und Multimediaberechnungen. Für den MMX-Nachfolger ISSE wurden neue 128 Bit Register eingeführt.
5.2.11
Welche Prozessorarchitekturen kennen Sie?
Vorsicht: Die folgenden Daten stammen aus vielen unterschiedlichen Quelle, die sich in einigen Punkten
auch klar widersprechen, sind also mit grosser Vorsicht zu behandeln.
54
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.2. Zentralprozessoren
Hersteller
Architektur
# Befehle
# Pipelines
# Pipelinestufen
1st level cache [kb]
2nd level cache [kb]
# Register
Registerlänge [Bit]
max Taktfrequenz [MHz]
# Transistoren
max SPECint2000
max SPECfp2000
5.2.12
MIPS 10k
Alpha 21164
Pentium II
Itanium
SGI
RISC
183
4?
5?
32D / 32I
?
?
?
250
6,8M
?
?
Compaq
RISC
≈ 200
4
7 / 10
8D / 8I
96
?
64
600
9,3M
928 (21264-C)
1482 (21364)
Intel
CISC
≈ 390
1
14
8D / 8I
offchip
8
32
2000
7,5M
1130 (Pentium 4)
1103 (Pentium 4)
Intel & HP
EPIC (RISC/CISC)
?
?
10
16D / 16I
96
> 256
64
1000
25M (ohne Cache)
674 (Itanium 2)
1431 (Itanium 2)
Wie viele Pipelinestufen haben moderne Prozessoren?
Die Intel P6 Architektur hat 14 Stufen.
5.2.13
Welche Probleme können beim Pipelining auftreten?
Die Probleme, die beim Pipelining auftreten können, nennt man Fliessbandhemmnisse, sie lassen sich
in drei Gruppen aufteilen.
Modifikation des Fliessbands durch explizite Ablaufbefehle. Sprungbefehle, Prozeduraufrufe, o. Ä.
stellen Fliessbandhemmnisse dar, da von der sequentielle Befehlsfolge abgewichen wird. Das für
die Befehlsholphase zuständige Teilwerk kann nicht einfach den nächsten Befehl holen, sondern
muss an eine bestimmte Stelle springen. Dies kann bei bedingten Sprüngen auch noch von einer
Berechnung abhängig sein. Die übliche Arbeitsweise des Teilwerks muss daher unterbunden werden.
Es können keinen neuen Befehle mehr in die Pipeline nachgefüllt werden, bis der neue Befehlszähler
zur Verfügung steht. Es gibt mehrere Techniken zur Optimierung.
Sprungzielspeicher. Der Sprungzielspeicher ist ein Puffer der die zuletzt angesprungenen Sprungziele speichert. Die Idee ist, dass ein einmal angesprungenes Ziel sehr wahrscheinlich nochmal
angesprungen wird, zum Beispiel bei Schleifen.
Verzögerter Sprung. Bei dieser Technik wird der auf den Verzweigungsbefehl folgende Befehl
vor der Verzweigung ausgeführt. Damit gibt man dem Leitwerk einen zusätzlichen Takt Zeit
auf den Sprungzielspeicher oder andere Quelle zuzugreifen. Verzweigungsbefehle die so vorgehen
heissen Delay Slot Befehle.
Spekulative Ausführung. Bei der spekulative Ausführung werden die Befehle auf einem der
beide Pfade der Verzweigung spekulativ ausgeführt. Die erzielten Ergebnisse werden dabei in
Schattenregistern gehalten und Notfalls wieder gelöscht.
Bedingte Ausführung. Die bedingte Ausführung kann bei Unterscheidungen, die sich nur in einem
Maschinenbefehl niederschlagen, angewandt werden. Der Befehl wird nur ausgeführt, wenn die
Bedingung war ist, sonst wird er übersprungen. Hierdurch realisiert man Fallunterscheidungen
ohne Verzweigungen.
Verzögerung in einzelnen Phasen des Fliessbands. Speicherzugriffe können durch Caches und
zusätzliche Puffer beschleunigt werden.
Datenabhängigkeiten. Fliessbandhemmnisse durch Datenabhängigkeiten können auftreten, wenn
der Befehl i + 1 Werte benötigt, die der Befehl i Berechnet. Es kann nur vorkommen, dass der
Befehl i seine Rückschreibephase noch nicht abgeschlossen hat und die Daten damit noch nicht
verfügbar sind. Dieses Probleme kann durch Bypasses gelöst werden. Die Ergebnisse, die die
ALU für den Befehl i berechnet hatte werden über Abkürzungen sofort zur Berechnung des
nächsten Befehls verwendet. Diese Bypasses reduzieren die Abkürzungen erheblich führen aber zu
sehr komplizierten Datenpfaden.
Generell gilt bei allen Problemen, dass die Compiler sehr viel zur Optimierung beitragen können (oder
müssen). So können sie z. B. durch geschickte Optimierung der Befehlsreihenfolge Datenabhängigkeit
vermeiden.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
55
Kapitel 5. Rechnerarchitektur
5.2.14
Wie verhält sich eine Pipeline bei einer Unterbrechung?
Wenn eine Unterbrechung auftritt, führt eine moderne Pipeline folgende Schritt durch.
1. Ein Trap-Befehl wird bei der nächsten Befehlsholphase in die Pipeline eingeführt.
2. Für den Befehl, der die Unterbrechung ausgelöst hat und für alle darauf folgenden Befehle, wird
Schreibzugriff generell abgeschaltet. Dies gilt nicht für Befehle, die vor dem Unterbrechung auslösenden
Befehl liegen.
3. Nach die dem Unterbrechungbehandlungsroutine abgelaufen ist, wird der Befehlszähler wieder auf
den unterbrechende Befehl gesetzt.
Wenn dieses Vorgehen bei einer Pipeline möglich ist, so spricht man von einer Pipeline mit Precise
Interrupts. Für aufwendige Fliesspunktbefehle ist es schwer dieses Verhalten sicher zustellen. Deshalb
haben moderne Prozessoren zwei Pipelines (oder zwei Betriebsmodi), die eine ist schnell, hat dafür keine
Precise Interrupts, die andere ist langsamer und hat Precise Interrupts. Precise Interrupts sind in der
Integerpipeline relativ einfach zu realisieren und werden dort auch realisiert, weil die Integerpipeline
zur Implementierung von Virtual Memory nötig ist.
5.2.15
Warum verwendet man bei modernen Rechner mehrere Pipelines?
siehe 5.2.16 und 5.2.14.
5.2.16
Warum geht es spezielle Pipelines für Festpunkt- und Fliesspunktarithmetik?
Wichtig für das Pipelining-Konzept ist, dass die Befehle in etwa gleiche Zeit in den einzelnen Pipelinestufen verbringen. Da Fliesspunktoperation in der Regel deutlich mehr Zeit als Festpunktoperationen
benötigen, ergeben sich Probleme bei der Mischung von beiden Befehlen. Eine Möglichkeit ist, sie auf
verschiedene Pipelines aufzuteilen. Die Synchronisation zwischen mehreren Pipelines kostest natürlich.
Ein anderer Grund sind die Unterbrechungen, siehe 5.2.14.
5.2.17
Wie lang dauert ein RISC-Befehl in etwa?
Ursprünglich war es so gedacht, dass ein RISC-Befehl in der Ausführungsphase einen Takt benötigt.
Angenommen er braucht in allen Phasen des Maschinenzyklus” einen Takt, so benötigt er bei streng
sequentieller Ausführung 5 Takte. Wenn Pipelining perfekt wäre würde er bei einer 5-stufigen Pipeline
im Durchschnitt 1 Takt benötigen. Mit geschätztem Overhead sagt man, dass eine Operation ca. 1,2
Takte benötigt.
5.2.18
Was sind Delay-Slot-Befehle?
siehe 5.2.13.
5.2.19
Was ist ein Sprungziel-Keller?
siehe 5.2.13.
5.2.20
Welche Adressierungsarten gibt es?
Es gibt virtuelle und physische Adressierung, für die Umsetzung ist die MMU zuständig.
5.2.21
Kennen Sie Beispiele für unkonventionelle Rechner?
Feldrechner: ein gewöhnlicher Programmspeicher, ein gewöhnliches Leitwerk, aber k Rechenwerke
in regulärer Anordnung.
Vektorrechner: ein gewöhnlicher Programmspeicher, ein gewöhnliches Leitwerk, ein m-stufiges Rechenwerk nach Pipelineprinzip, in dem m Komponenten von Vektoren in verschiedenen Phasen der
gleichen Operation sind.
assoziativer Rechner: ein gewöhnlicher Programmspeicher, ein gewöhnliches Leitwerk, alle Daten
und Befehle in p Zellen eines assoziativen Speichers, d. h. Auswahl der Zellen nur durch inhaltliche
Kriterien, nicht durch Adressen
56
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.3. Hauptspeicher und Verkehrswege
5.3
Hauptspeicher und Verkehrswege
5.3.1
Page Faults werden woran erkannt und von wem behandelt?
Seitenfehler werden von der MMU erkannt, diese löst bei einem Seitenfehler eine Unterbrechung aus, die
von einer Unterbrechungsroutine des Betriebssystems behandelt wird. Seiten-Ein- und Auslagerungsstrategien stecken in dieser Routine.
5.3.2
5.3.3
Speicherhierarchie mit Zugriffszeiten aufzählen.
Speicher
Zugriffszeit
(Prozessortakt 2.5 ns)
Kapazität
Register
Primär-Cache
Sekundär-Cache
Hauptspeicher
Plattenspeicher
Archivspeicher
< 2.5 ns
2.5 - 10 ns
5 - 50 ns
50 - 500 ns
5 - 15 ms
> 50 ms
256 - 1024 Bytes
1 - 128 KB
265 KB - 4MB
≤ 4 GB
≤ 200 GB
mehrere TB
Was ist Caching?
Ein Cache ist ein schneller Pufferspeicher zwischen den Registern und dem Hauptspeicher. Darin sind
sowohl Programmteile wie Daten enthalten. Diese können entweder zusammen in einem Unified Cache
liegen oder es gibt zwei getrennte Caches (Split Cache). Bei jedem Speicherzugriff des Prozessors testet
die Cache Steuerlogik des Caches, ob das Speicherwort im Cache vorliegt (Cache Hit) oder nicht (Cache
Miss). Falls es vorliegt wird es direkt vom Cache in den Prozessor übertragen. Falls ein Cache Miss
auftritt, wird aus dem Hauptspeicher ein Block von Worten in den Cache übertragen. Hauptspeicher
und Cache sind in Blöcken organisiert.
Wegen der hohen Geschwindigkeit wird der Cache durch Hardware verwaltet, der Zugriff erfolgt transparent. Programmierer, Übersetzer und Betriebssysteme sollten den Cache aber insofern beachten, dass
sie Daten und Programm für das Caching optimieren. So wird eine Programmschleife sicherlich deutlich
schneller abgearbeitet, wenn sie komplett in den Cache passt.
Moderne Systeme haben meistens eine Cache-Hierarchie bestehend aus dem Primary Cache und dem
Secondary Cache die sich in Grössen und Geschwindigkeit unterscheiden.
Primary Cache. Der Primary Caches ist auf dem Prozessor-Chip integriert und meist als Split
Cache realisiert. Die Cache Blöcke sind meist nicht länger als 32 Bytes und damit in wenigen
Zyklen nachladbar.
Secondary Cache. Bis vor kurzem wurde der Secondary Cache ausserhalb des Prozessors realisiert,
Prozessoren wie der Pentium III haben ihn aber bereits On Die. Der Secondary Cache ist meist
ein Unfied Cache mit Blockgrössen um die 128 Byte.
5.3.4
Was für Adressierungsmöglichkeiten gibt es bei Caches?
Caches können entweder mit realen oder virtuellen Adressen adressiert werden, beides hat Vor- und
Nachteile.
Virtuelle Adressierung. Der Vorteil virtueller Caches ist, dass sie schneller sind, da Cache-Zugriff
und Adressübersetzung durch die MMU können parallel stattfinden. Im Mehrprozessbetrieb werden
virtuelle Caches aber einige Probleme auf.
Dieselbe virtuelle Adressen von verschiedenen Prozessen kann auf unterschiedliche physische
Adresse verweisen, deshalb muss beim Kontextwechsel der Cache gelöscht werden.
Unterschiedliche virtuelle Adressen können auf dieselbe physische Adresse verweisen, z. B. bei
gemeinsamen Variablen. Um Inkonsistenzen im Cache zu vermeiden sollten gemeinsame Daten
nicht gecachet werden.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
57
Kapitel 5. Rechnerarchitektur
Wenn Hauptspeicherdaten durch DMA Zugriffe verändert werden, liegt eine Dateninkonsistenz
vor. Das Problem bei virtueller Adressierung ist das Rückermitteln der virtuellen Adressen aus
den physischen Adressen.
Virtuelle Caches werden deshalb hauptsächlich bei prozessorinternen Befehls-Caches eingesetzt.
Reale Adressierung. Caches mit physischer Adressierung sind langsamer, da die Adressübersetzung
abgewartet werden muss. Dafür sind sie für Inkonsistenzen nicht so anfällig. Zum Beispiel kann die
DMA-Einheit, die real adressiert, hier für die Konsistenz sorgen.
5.3.5
Was für Cache-Organisationsformen gibt es?
Die Organisationsform des Caches legt das Mapping von Hauptspeicher-Blöcken auf Cache-Blöcke und
wie ein gewünschter Block im Cache aufzufinden ist (Identifikationsproblem) fest. Die folgenden Organisationsformen sind gebräuchlich.
Direkte Abbildung. In einem Cache mit direkter Abbildung und N Blöcken, wird der Hauptspeicherblock B im Cache-Block B mod N gespeichert. Diese Abbildung ist die einfachste, da nur ein
Vergleicher benötigt wird. Das Problem ist, dass Cache-Einträge sehr schnell wieder verdrängt
werden.
Voll assoziative Abbildung. In einem voll assoziativen Cache kann ein Hauptspeicherblock in jedem
Cache-Block gespeichert werden. Voll assoziative Caches sind teuer, da man N Vergleicher benötigt.
Die Verdrängung ist hier zwar am geringsten, aber sie sind langsam.
n-fach assoziative Abbildung. Bei n-fach assoziative Caches wird der Cache in M = N/n Sätze
mit jeweils n Blöcken geteilt. Der Hauptspeicher Block B kann im einem Cache-Block des Satz B
mod M gespeichert werden. Wenn n = N ist, wird der Cache voll assoziativ, wenn n = 1 entspricht
er einem Cache mit direkter Abbildung. n-fach assoziative Caches bieten die Möglichkeit eine guten
Kompromiss zwischen Kosten, Geschwindigkeit und Wirksamkeit zu finden. In der Praxis werden
2,4 und 8-fach assoziative Caches eingesetzt.
Da jedem Cache-Block eine grosse Anzahl an Hauptspeicherblöcken zugeordnet ist, braucht man einen
Mechanismus um Hauptspeicherblöcke eindeutig zu identifizieren. Dazu wird pro Cache-Block neben
ein paar Verwaltungsbits auch noch eine Kennung gespeichert, die der Hautpspeicheradresse entspricht.
5.3.6
Welche Aktualisierungsstrategien gibt es bei Caches?
Wenn Daten im Cache verändert werden, stellt sich die Frage, wann diese Änderungen in den Speicher
zurückgeschrieben werden um die Konsistenz zu erhalten. Es gibt zwei Strategien
Durchschreiben (Write Through). Durchschreiben bedeutet, dass jede Änderung im Cache sofort
auch in den Hauptspeicher geschrieben wird. Dadurch wird die Datenkonsistenz gewährleistet, aber
der Prozessor-Speicherbus stark belastet. Primary Caches arbeiten meist nach diesem Prinzip.
Zurückschreiben (Write Back ). Bei Write Back wird der Hauptspeicher erst aktualisiert, wenn ein
veränderter Cache-Block verdrängt wird. Dazu muss ein Dirty-Bit verwaltet werden. Secondary
Caches arbeiten meist so.
5.3.7
Welche Ersetzungsstrategien werden bei Caches eingesetzt?
Bei Caches wird meist eine LRU-Strategie eingesetzt, wobei aber in den Cache-Blöcken eine Altersinformation gespeichert werden muss. Eine sehr einfach zu implementierende Strategie ist das zufällige
auswählen der zu ersetzenden Seite. Diese Strategie liefert überraschend gute Ergebnisse.
5.3.8
Was fällt Ihnen zum Thema Leistung von Caches ein?
Leistungsbetrachtung von Caches orientieren sich meist an der Formel für die mittlere Speicherzugriffszeit Te für eine zweistufige Speicherhierarchie.
Te = h · T h + m · T m
58
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.4. Ein-/Ausgabewerk
Wobei h und m = 1 − h die Treffer- bzw. Fehlerraten (Hit rate, miss rate) im Cache sind. T h ist
die Cache-Zugriffszeit (Hit time) und Tm die Cache-Ladezeit (miss time). Die Zugriffszeit Te kann
durch die folgende drei Massnahmen verbessert werden. Optimieren einer Grösse bewirkt meist die
Verschlechterung einer anderen Grössen, es gilt einen Kompromiss zu finden.
Reduktion der Fehlerrate m. Entweder kann der Cache vergrössert oder die Assoziativität erhöht
werden. Dadurch wird er teurer und die Cache-Zugriffszeit wird erhöht. Durch grössere Blöcke
können Lokalitätseigenschaften besser genutzt werden, dafür wird die Ladezeit grösser. Weitere
Möglichkeiten sind der Einsatz eines Victim Cache und Prefetching.
Reduktion der Cache-Zugriffszeit Th . Die Cache-Zugriffszeiten für den Primary Cache sind entscheidend für die Prozessortaktrate, Zugriffszeiten auf den Secondary Cache bestimmen die Wartezyklen
des Prozessors. Kurze Zugriffszeiten erhält man bei kleinen und einfach organisierten Caches, was
den obigen Optimierungen zuwiderläuft.
Reduktion der Cache-Ladezeit Tm . Cache-Ladezeiten können durch Einführung einer weiteren Ebene in der Speicherhierarchie verbessert werden. Eine andere Möglichkeit ist die Verwendung von
Non-Blocking Caches die Daten an den Prozessor liefern können während sie aus dem Hauptspeicher
Daten nachladen. Ausserdem ist Tm massgeblich durch die Geschwindigkeit des Prozessor-SpeicherBusses und die Hauptspeicherzugriffszeiten bestimmt.
5.3.9
Was beeinflusst den Zugriff auf den Hauptspeicher?
Hauptspeicherzugriffszeiten
Geschwindigkeiten des Prozessor-Speicher-Busses.
Anzahl und Effizienz der Caches
5.3.10
Wie kann man den Zugriff auf den Hauptspeicher beschleunigen?
Durch Caching, siehe 5.3.3
5.3.11
Wie verläuft die Kommunikation Prozessor-Hauptspeicher?
Über den Prozessor-Speicher-Bus. Zusätzlich werden meist ein oder mehrere Caches dazwischen geschaltet.
5.3.12
Wie funktioniert Busverwaltung?
Ein Busmaster muss das Recht erwerben auf dem Bus zu senden. Wenn es nur einen Busmaster gibt,
ist die Vergabe einfach. Bei mehreren Mastern muss irgendwie geregelt werden, wer das Recht erhält.
Es gibt Verfahren mit einer zentralen Steuereinheit und mit dezentralen Einheiten in den Busmastern.
Diese können prioritätengesteuert oder fair sein.
5.3.13
Was ist Daisy-Chaining?
Beim Daisy-Chaining wird der Bus sozusagen durch die Geräte hindurchgeführt. Die Daten gehen in
ein Geräte hinein, werden dort eventuell verarbeitet, und dann wieder raus zum nächsten Gerät.
5.4
Ein-/Ausgabewerk
5.4.1
Welche Varianten gibt es für E/A-Operationen?
Die Gerätekontrolle haben Register über die sie gesteuert und über die Daten ausgelesen werden können.
Es gibt zwei Möglichkeiten, wie diese Register angesprochen werden können:
I/O-Ports. Hier wird den Registern der Controller eine I/O-Port-Nummer zugeordnet, zusätzlich
gibt es spezielle IN/OUT Befehle. So kann z. B. mit IN RX, port der entsprechende Wert in ein
CPU-Register geladen werden.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
59
Kapitel 5. Rechnerarchitektur
Memory-Mapped I/O. Bei Memory-Mapped-IO werden die Register der Controller in Hauptspeicher
eingeblendet. Nun kann auf die Register mit ganz normalen Move-Befehlen zugegriffen werden. Der
Vorteil ist, dass man keine speziellen I/O-Befehle benötigt. Ausserdem kann der Zugriff auf Geräte
durch die normalen Speicherschutzmechanismen realisiert werden. Auf Maschinenebene können
Befehle eingespart werden, da der Wert nicht zwangsweise in ein Register geladen werden muss.
Probleme ergeben sich durch das Caching, cachen von gemapten Adressen macht keinen Sinn, daher muss die Hardware dafür sorgen, dass das Caching für diese Adressen ausgeschaltet wird. Bei
Memory-Mapped I/O müssen alle Gerätekontroller bei jedem Speicherzugriff aufpassen, ob nicht
sie gemeint sind. Das ist kein Problem, solange I/O und Speicher am selben Bus hängen. Gibt
es aber einen dedizierten Prozessor-Speicher-Bus, so muss man irgendwie zwischen echten Speicherzugriffen und Zugriffen auf Geräte unterscheiden. Dafür gibt es wiederum verschieden Ansätze.
Bei Pentium gehen deshalb Speicherzugriffe durch die PCI-Bridge, die die Unterscheidung macht.
Es gibt auch Systeme, z. B. Pentium, die beide Verfahren nutzen.
5.4.2
Was ist DMA?
DMA steht für Direct Memory Access und wird benutzt um die CPU bei I/O-Zugriffen zu entlasten.
Wenn DM eingesetzt wird, gibt es einen DMA-Controller. Will die CPU Daten von einem Geräte lesen,
gibt sie dem DMA-Controller den entsprechenden Auftrag und wendet sich wieder ihrer Arbeit zu. Der
DMA-Controller kopiert jetzt eigenständig Daten von dem Gerät in den Hauptspeicher. Dabei können
Geräte nicht unterscheiden ob der Zugriff von der CPU oder dem DMA-Controller kommt. Wenn er
damit fertig ist, schickt er eine Unterbrechung an die CPU. Damit kann die CPU vom einem Grossteil
der I/O-Arbeit entlastet werden.
60
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
5.5. SPEC-Werte
5.5
SPEC-Werte
Die folgenden Werten stammen von der SPEC-Website (www.spec.org) vom 16.03.2003. Die ersten 5 zeigen bei
beiden Benchmarks die Top-5 von diesem Tag, die anderen sind beliebig ausgewählt.
CINT2000
Company
System
Peak
Base
Processor
Published
Dell
Precision WorkStation 350 (3.06
GHz P4)
Intel D850EMVR motherboard (3.06
GHz, Pentium 4 processor with HT
Technology)
Precision WorkStation 340 (3.06
GHz P4)
Precision WorkStation 350 (2.8 GHz
P4)
Intel D850EMVR motherboard (2.8
GHz, Pentium 4 processor)
1130
1085
Dec-2002
1107
1099
1074
1032
1061
1017
1040
1032
Intel Pentium 4 (533 MHz system
bus)
Intel Pentium 4 Processor with HT
Technology (3.06 GHz, 533 MHz
bus)
Intel Pentium 4 (533 MHz system
bus)
Intel Pentium 4 (533 MHz system
bus)
Pentium 4 processor (2.8 GHz, 533
MHz bus)
Precision WorkStation 340 (2.4 GHz
P4)
Intel D850MD motherboard (2.4
GHz, Pentium 4 processor)
Precision WorkStation 340 (2.2 GHz
P4)
Precision WorkStation 340 (2.0A
GHz P4)
Intel D850EMV2 motherboard (2.0A
GHz, Pentium 4 processor)
Gigabyte GA-7DX Motherboard,
AMD Athlon (TM) XP 1800+
PRIMEPOWER650 (810MHz)
905
865
Sep-2002
833
819
833
798
759
738
Intel Pentium 4 (533 MHz system
bus)
Pentium 4 processor (2.4 GHz, 400
MHz bus)
Intel Pentium 4 (400 MHz system
bus)
Intel Pentium 4
759
756
644
Intel
Dell
Dell
Intel
Dell
Intel
Dell
Dell
Intel
AMD
Fujitsu
Siemens
Dell
Compaq
HP
PowerEdge 1500SC (1.26 GHz PIII)
AlphaServer GS160 Model 16
68/1001
hp workstation j6700
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
Dec-2002
Dec-2002
Dec-2002
Oct-2002
Apr-2002
Sep-2002
Feb-2002
621
Pentium 4 processor (2.0A GHz, 400
MHz bus)
AMD Athlon (TM) XP 1800+
Sep-2002
Oct-2001
624
512
SPARC64 GP
Jul-2002
623
621
611
561
Intel Pentium III
Alpha 21264C
Feb-2002
Jul-2001
603
569
PA-8700
May-2001
61
Kapitel 5. Rechnerarchitektur
CFP2000
Company
System
Peak
Base
Processor
Published
HP
HP
AlphaServer GS1280 7/1150
hp server rx5670 (1000 MHz,
Itanium 2)
hp server rx2600 (1000 MHz,
Itanium 2)
hp workstation zx6000 (1000 MHz,
Itanium 2)
hp AlphaServer ES45 68/1250
1482
1431
1124
1431
Alpha 21364
Intel Itanium 2
Jan-2003
Dec-2002
1427
1427
Intel Itanium 2
Dec-2002
1422
1422
Intel Itanium 2
Dec-2002
1365
1019
Alpha 21264C
Nov-2002
1060
1048
Dec-2002
1048
1034
1036
1024
1024
1012
844
843
733
782
Intel Pentium 4 (533 MHz system
bus)
Pentium 4 processor (2.8 GHz, 533
MHz bus)
Intel Pentium 4 (533 MHz system
bus)
Pentium 4 processor (2.67 GHz, 533
MHz bus)
UltraSPARC III Cu
AMD Athlon (TM) XP 2800+
Mar-2003
Oct-2002
831
772
AMD Athlon (TM) XP 2700+
Oct-2002
628
618
Aug-2001
607
591
Pentium 4 processor (1.8 GHz, 400
MHz bus)
Intel Pentium 4
May-2001
604
561
AMD Athlon (TM) XP 1700+
Oct-2001
HP
HP
HP
Dell
Intel
Dell
Intel
Sun
AMD
AMD
Intel
Dell
AMD
62
Precision WorkStation 350 (2.8 GHz
P4)
Intel D850EMVR motherboard (2.8
GHz, Pentium 4 processor)
Precision WorkStation 350 (2.66
GHz P4)
Intel D850EMVR motherboard (2.67
GHz, Pentium 4 processor)
Sun Fire V1280 (900MHz)
ASUS A7N8X (REV 1.02)
Motherboard, AMD Athlon (TM)
XP 2800+
ASUS A7N8X (REV 1.02)
Motherboard, AMD Athlon (TM)
XP 2700+
Intel D850GB motherboard(1.8
GHz, Pentium 4 processor)
Precision WorkStation 330 (1.70
GHz P4)
Epox 8KHA+ Motherboard, AMD
Athlon (TM) XP 1700+
Oct-2002
Dec-2002
Oct-2002
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
Kapitel 6
Betriebssysteme
6.1
Allgemeines
6.1.1
Was für Arten von Betriebsmitteln gibt es?
Betriebsmittel können wie folgt klassifiziert werden.
einmalig benutzbar. Druckerpapier, Nachricht
wiederholt benutzbar.
parallel benutzbar. Datei mit lesendem Zugriff
exklusiv benutzbar, unterbrechbar. CPU
exklusiv benutzbar, nicht-unterbrechbar. Drucker
6.1.2
Was ist ein Betriebssystem?
Ein Stück Software, das die in 6.1.3 beschriebenen Aufgaben erfüllt.
6.1.3
Was sind die Aufgaben eine Betriebssystems?
Veredeln der Hardware (Virtualisierung)
Steuerung und Kontrolle der Programmausführung
Verwaltung der Betriebsmittel
Anbieten von Diensten in Form von Schnittstellen, so dass die Betriebsmittel genutzt werden
können.
Schutz mehrerer gleichzeitig aktiver Benutzer
6.2
Prozesse und Threads
6.2.1
Was ist ein Prozess?
Ein Prozess ist eine Abstraktion eines laufenden Programmes. Mit einem Prozess verbunden sind:
Thread of Control
Adressraum
globale Variablen
offene Dateien
Kindprozesse
Register
Befehlszähler
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
63
Kapitel 6. Betriebssysteme
Stack
Status
6.2.2
Was ist ein Thread?
Ein Thread könnte als leichtgewichtiger Prozess bezeichnet werden. Er hat
Thread of Control
Register
Befehlszähler
Stack
Status
Er hat aber keinen eigenen
Adressraum
globale Variablen
offene Dateien
Kindprozesse
6.2.3
Was bedeutet Mehrprogrammbetrieb?
Wenn mehrere Prozesse sich eine CPU teilen spricht man von Mehrprogrammbetrieb.
6.2.4
Wie kommunizieren Prozesse miteinander?
Prozesse können kommunizieren über:
gemeinsamen Speicher
gemeinsame Dateien
Nachrichten
Semaphoren
RPC
Pipes
Mailslots (Windows)
6.2.5
Was beinhaltet der Prozesskontext?
Prozessmanagement
Speichermanagement
Dateimanagement
Register
Zeiger auf Codesegment
Root-Verzeichnis
Befehlszähler
Zeiger auf Datensegment
Arbeitsverzeichnis
Prozess-Status-Wort
Zeiger auf Stacksegment
File Handles
Stackpointer
User ID
Prozessstatus
Gruppen ID
Priorität
PID
6.2.6
64
Welche Zeitscheibenverfahren gibt es?
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.2. Prozesse und Threads
Round-Robin
Round-Robin mit Prioritäten
6.2.7
Welche Möglichkeiten gibt es zur Prozesssynchronisation?
Unterbrechungssperre
Verdrängungssperre
Sperrvariablen
algorithmische Lösungen
Semaphore
Monitore
6.2.8
Was ist ein Scheduler?
Der Scheduler ist der Teil des Betriebssystems, der entscheidet, wann welcher Prozess Rechenzeit bekommt. Er folgt einem Scheduling Algorithmus.
6.2.9
Was ist ein Dispatcher?
In Multithreadinganwendung gibt es oft einen Dispatchthread. Dieser hat die Aufgabe die Arbeit an
andere Threads zu verteilen.
6.2.10
Erzählen Sie etwas zu Scheduling-Strategien.
Man muss unterscheiden zwischen Scheduling-Strategien für
Batch-Systeme. Für Batch-Systeme gibt es folgende Algorithmen
First-Come First-Served. Sehr einfach umzusetzen, wegen der Nicht-Unterbrechbarkeit aber
nicht praktikabel.
Shortest Job First. Beweisbar kürzeste Verweilzeit (siehe 6.2.11), aber nicht unterbrechbar und
die Job-Grösse muss im voraus bekannt sein.
Shortest Remaining Time Next. Hier wählt der Scheduler immer den Prozess mit der kleinsten
Restlaufzeit. Auch hier müssen Berechnungszeiten im voraus bekannt sein.
Interaktive Systeme.
Round-Robin. Jedem Prozess wird ein Zeitintervall, das Quantum, zugeordnet, in dem er laufen
kann, danach wird zu einem neuen Prozess gewechselt. Die Prozesse können in einer Liste
verwaltet werden. Wenn ein Prozess sein Quantum aufgebraucht hat (oder abgegeben hat)
wird an das an der Liste angehängt und der Prozess am Kopf der Liste gestartet. Die Wahl
der Länge des Quantums ist entscheidend. Ist das Quantum zu kurz, gibt es zu viele (teure)
Kontextwechsel, ist es zu lang, sind die Antwortzeiten schlecht. In der Praxis werden Quanta
der Länge 20–50 ms eingesetzt.
Prioritäten. Beim Prioritäten-Scheduling wird jedem Prozess eine Priorität zugeordnet. Der
Scheduler wählt immer den Prozess mit der höchsten Priorität. Damit dieser nicht für immer
Läuft, bricht man nach einem bestimmten Zeitquantum ab und nimmt den nächsten. Oder man
verringert die Priorität des Prozesses entsprechend seiner Laufzeit. Falls seine Priorität unter
dies eines anderen fällt, wird gewechselt.
Generell können die Prioritäten statisch oder dynamisch vergeben werden. Bei der dynamischen
Vergabe gibt es folgende Varianten. Viele Prozesse verbringen sehr viel Zeit mit I/O und belasten
die CPU nur wenig. Solchen Prozessen sollte man die CPU so prompt wie möglich zur Verfügung
stellen (wenn sie sie benötigen) damit sie sich weiter mit I/O befassen können und die CPU für
rechenintensive Prozesse frei bleibt. Eine einfache Möglichkeit, diesen Service anzubieten, ist,
den Prozessen die Priorität 1/f zuzuweisen. Wobei f der Bruchteil des Quantums ist, den
der Prozess beim letzten mal benutzt hat. Prozesse die ihr Quantum fast gar nicht nutzen,
bekommen eine hohe Priorität, Prozesse die ihr Quantum voll nutzen eine niedrige Priorität.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
65
Kapitel 6. Betriebssysteme
Round-Robin + Prioritäten. In der Praxis wird oft eine Kombination der beiden Schedulingstrategien eingesetzt. Die Prozesse werden in mehrere Kategorien (nach Prioritäten) eingeteilt
und in innerhalb dieser Kategorien wird Round-Robin Scheduling gemacht. Das heisst der Scheduler macht solange Round-Robin in der wichtigsten Kategorien bis dort keine Prozesse mehr
vorhanden sind, dann nimmt er sich die nächste Kategorie vor. Auch hier sollten die Prioritäten
dynamisch angepasst werden, sonst besteht die Gefahr des Verhungerns.
Shortest Process Next. Shortest Process Next ist der Versuch die optimalen Verweilzeiten von
Shortest Job First in interaktive Systemen zu nutzen. Dazu geht man davon aus, dass interaktive Prozesse immer nach dem Muster Warten auf Befehl, Befehl ausführen, Warten auf
Befehl, Befehl ausführen ablaufen. Wenn man die Ausführung eines Befehls als Job betrachtet, kann man die Antwortzeiten minimieren in dem man die kürzesten Befehl zuerst bearbeitet. Um herauszufinden, welcher der kürzeste Befehl ist, wird eine Technik namens Aging
eingesetzt.
Garantiertes Scheduling. Bei diesem Verfahren werden den Benutzer Garantien wie bei N Benutzern bekommt jeder genau 1/N der Rechenleistung gegeben und diese Versucht einzuhalten.
Dies ist schwierig zu implementieren.
Lottery. Hier bekommt jeder Prozessor ein Los . Wenn eine Schedulingentscheidung getroffen
werden muss, wird eine Losnummer ausgelost. Der Prozess mit der gezogenen Nummer erhält
den Prozessor. Um Prioritäten zu realisieren kann bestimmten Prozessen mehr als ein Los
gegeben werden und damit ihre Gewinnchancen erhöht werden. Lottery Scheduling bietet einige
interessante Möglichkeiten, so können z. B. Prozesse ihre Lose an andere Prozesse verschenken.
Ein Client, der unbedingt eine Information von einem Server braucht, könnte seine Lose an den
Server verschenken, damit dieser möglichst schnell Rechenzeit bekommt.
Fair-Share. Beim Fair-Share Scheduling bezieht der Scheduler zusätzlich Informationen über
den Besitzer eines Prozesses in Betracht und achtet darauf, dass alle Benutzer ungefähr gleich
viel Rechenzeit erhalten.
Echtzeit-Systeme. Schedulingalgorithmen für Real-Time Systeme können entweder statisch oder
dynamisch sein. Statische Algorithmen weisen jedem Prozess eine feste Priorität und verwenden
dann Prioritätenscheduling. Bei dynamischen Algorithmen können sich die Prioritäten ändern.
Rate Monotonic. RMS ist ein statischer Algorithmus der jedem Prozess eine Priorität entsprechend der Frequenz des Ereignis, das diesen Prozess triggert, zuweist. Dazu müssen die
Ereignisse periodisch auftreten und die Abarbeitung eines Ereignisses muss immer gleich lang
dauern.
Earliest Deadline First. Ein typische dynamischer Algorithmus ist EDF. Wenn ein Prozess die
CPU benötigt meldet er sich an und gibt den Termin zu dem er fertig sein muss an. Die Prozesse
werden in einer Liste verwaltet und der Scheduler wählt immer den Prozess mit der knappsten
Deadline.
Eine weitere Möglichkeit bietet die Trennung von Mechanism und Policy. Wenn Programme aus mehreren Prozessen bestehen haben sie meisten eine sehr viel bessere Vorstellung davon wie diese geschedult
werden sollen als der Scheduler des Betriebssystems. Ein Möglichkeit diese Information zu nutzen ist
Betriebsystemfunktionen zur Verfügung zu stellen die es einem Prozess erlauben, die Prioritäten seiner
Kindprozesse zu verändern. Hier steckt der Mechanism im Kernel aber die Policy wird durch einen
Userprozess bestimmt.
6.2.11
Welche Strategie führt zu kürzesten Verweilzeiten?
Shortest Job First. Angenommen es gibt 4 Prozesse A, B, C, D, wobei deren Bearbeitungszeiten a, b, c, d
sind. Wenn die Prozesse in alphabetischer Reihenfolge ausgeführt werden, dann sind jeweiligen Verweilzeiten für die Prozesse
66
T (A)
=
a
T (B)
T (C)
= a+b
= a+b+c
T (D)
=
a+b+c+d
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.2. Prozesse und Threads
Das ergibt eine durchschnittliche Verweilzeit von
T (∅)
=
=
T (A) + T (B) + T (C) + T (D)
4
4a + 3b + 2c + d
4
Wie man sieht, hat die Laufzeit des ersten Prozesses den grössten Einfluss, daher führt SJF zu den
kürzesten Verweilzeiten.
6.2.12
Ist Shortest Job First unterbrechbar?
Nein. Ist gibt aber eine unterbrechbare Version, die sich Shortest Remaining Time Next nennt. Hier
wählt der Scheduler immer den Prozess mit der kleinsten Restlaufzeit. Auch hier müssen Berechnungszeiten im voraus bekannt sein.
6.2.13
Welche unterbrechbare Strategie liefert die kürzesten Verweilzeiten?
Shortest Remaining Time Next.
6.2.14
Arbeitet das Prioritätenscheduling mit statischen Prioritäten?
siehe 6.2.10.
6.2.15
Wie funktionieren dynamische Prioritäten?
siehe 6.2.10.
6.2.16
Wonach bewertet man Schedulingstrategien?
Je nach Art des Systems verfolgen die Strategien unterschiedliche Ziele. Für alle System gilt:
Fairness.
Policy Enforcement. Der Scheduler muss die System-Policy durchsetzen.
Balance. Alle Teile des Systems sollten ausgelastet sein.
Für interaktive Systeme gilt:
Response Time.
Proportionality. Das Scheduling sollten den Erwartungen des Users entsprechen. Zum Beispiel
macht es dem User in den meisten Fällen nichts aus, wenn das Versenden einer eMail 20s dauert,
es stört in aber wenn das Eingeben eines Buchstabens 20s dauert.
Für Batch-Systeme gilt:
Throughput. Anzahl der Jobs pro Stunde maximieren.
Turnaround Time. Verweilzeiten minimieren.
CPU Utilization. CPU-Auslastung maximieren.
6.2.17
Wie schützt das Betriebssystem den Speicherbereich eines Prozesses vor Zugriffen von anderen Prozesses?
Das muss die Hardware erledigen, die muss vom Betriebssystem richtig konfiguriert werden.
6.2.18
Wie läuft eine Unterbrechung genau ab?
1. Hardware speichert Befehlszähler, PSW usw. auf dem aktuellen Stack
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
67
Kapitel 6. Betriebssysteme
2. Hardware setzt Befehlszähler entsprechend des Interrupt Vectors
3. Assembler-Routine sichert die Register
4. Assembler-Routine legt neuen Stack an
5. C-Routine mit Unterbrechungscode wird gestartet
6. Scheduler wählt neuen Prozess
7. Rücksprung von der C-Routine zur Assembler-Routine
8. Zurückkopieren der Register, usw., Starten des (neuen) aktuellen Prozesses
6.2.19
Was für Arten von Unterbrechungen gibt es?
Interrupts lassen sich nach vielen Kriterien klassifizieren, z. B. Software vs. Hardware, Maskable vs
Non-Maskable, Precise vs Imprecise.
6.2.20
Was beinhaltet der Prozesskontrollblock?
Der Prozesskontrollblock ist eine Datenstruktur, die den Prozesskontext beschreibt. Siehe 6.2.5.
6.2.21
Was ist der Unterschied zwischen Ports und Sockets?
Ein Socket ist ein Kommunikationsendpunkt. Sockets sind für Kommunikation zwischen zwei Rechnern
gedacht. Ein Socket setzt sich zusammen aus Adresse und Port.
6.2.22
Wie realisiert man Semaphoren in der Praxis?
Falls ein TSL-Befehl zur Verfügung steht können Semaphoren wie in 6.2.23 realisiert werden. Ansonsten werden sie meist vom Betriebssystem durch kurzzeitiges Sperren der Interrupts realisiert. Das
Betriebssystem stellt den Userprozessen dann entsprechende Funktionen zur Verfügung.
6.2.23
Wie wird wechselseitiger Ausschluss umgesetzt?
Es gibt verschiedene Möglichkeiten wechselseitigen Ausschluss umzusetzen.
Interrupts sperren. Ein Prozess könnte, bevor er eine kritischen Bereich betritt einfach alle Interrupts sperren. Das hat mehrere Nachteile. Ersten sollte in Userprozess nicht das Recht haben
Interrupts zu sperren, zweitens funktioniert dies in Mehrprozessorsystemen nicht. Innerhalb des
Betriebssystems kann das Sperren von Interrupt manchmal eingesetzt werden, für Userprozesse
sollte es aber nicht in Frage kommen.
Test and Set Locks. TSL ist eine Befehl, der von der Hardware angeboten wird. Er liest ein Wort
aus dem Speicher und speichert es in einem Register. Anschliessend schreibt z. B. 1 an die Stelle
im Speicher. Die Hardware garantiert, dass dieser Befehl ununterbrechbar ist. Der folgende Code
zeigt wie mit diesem Befehl wechselseitiger Ausschluss realisiert werden kann:
enter:
TSL REG, lock
CMP REG, 0
JNE enter
RET
kopiere lock in das Register REG und setze lock auf 1
war lock = 0 ?
es war nicht 0, also war die Sperre bereits gesetzt ⇒ Schleife
zurück zum Aufrufer, kritischer Bereich wurde betreten
MOV lock, 0
RET
0 in lock speichern und dadurch Sperre frei geben
zurück zum Aufrufer, kritischer Bereich wurde verlassen
exit:
Natürlich müssen die beiden Prozeduren beim Betreten bzw. Verlassen des kritischen Bereichs
aufgerufen werden. Das Problem ist, dass diese Implementierung Busy-Waiting benutzt.
68
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.3. Deadlocks
Mutexes. Mutexes sind nicht anderes als binäre Semaphoren. Sie sind ideal um wechselseitigen
Ausschluss zu realisieren. Meist werden sie als Betriebssystemfunktionen implementiert, z. B. durch
Sperren von Interrupts. Falls ein TSL-Befehl zur Verfügung steht können sie aber auch sehr einfach
im Userspace implementiert werden.
mutex lock:
TSL REG, mutex
CMP REG, 0
JZE ok
CALL thread yield
JMP mutex lock
ok:
RET
mutex unlock:
MOV mutex, 0
RET
6.3
Deadlocks
6.3.1
Was sind Deadlocks?
kopiere mutex in das Register REG und setze mutex auf 1
war mutex = 0 ?
es war Null, also alles klar
es war nicht 0, also war die Sperre bereits gesetzt ⇒ schlafen gehen
Thread ist wieder aufgewacht, nochmal probieren
zurück zum Aufrufer, kritischer Bereich wurde betreten
0 in mutex speichern und dadurch Sperre frei geben
zurück zum Aufrufer, kritischer Bereich wurde verlassen
Eine Menge von Prozessen ist in einem Deadlock wenn jeder Prozess auf ein Ereignis wartet, das nur
von einem anderen Prozess ausgelöst werden kann.
6.3.2
Welche Verfahren gibt es mit Deadlocks umzugehen?
1. Vogel-Strauss-Algorithmus. Mann hofft darauf, dass keine Deadlocks auftreten. Dies ist das in der
Praxis am häufigsten verwendete Verfahren.
2. Deadlock-Erkennung. Man versucht zu erkennen, dass ein Deadlock aufgetreten ist und die Situation
dann zu bereinigen.
3. Deadlock-Vermeidung. Man versucht Deadlocks durch vorsichtige Vergabe der Betriebsmittel zu
vermeiden.
4. Deadlock-Verhinderung. Man versucht Deadlocks generell zu verhindern, in dem man eine der vier
Deadlock-Bedingung ausschliesst.
6.3.3
Wie funktioniert Deadlock-Erkennung?
Um einen Deadlock zu finden muss man einen Kreis im Betriebsmittelgraphen finden. Falls ein Deadlock
gefunden wurden, gibt es verschiedene Methoden damit umzugehen.
Recovery through Preemption. Wenn möglich entzieht man einem der Prozesse ein Betriebsmittel.
Selbst wenn dies theoretisch möglich ist, ist es schwer automatisch festzustellen welchem Prozess
welches Betriebsmittel zu entziehen ist.
Recovery through Rollback. Man kann Prozesse zwingen hin und wieder sog. checkpoints zu speichern. In diesen wird der komplette Status eines Prozesses festgehalten. Wenn nun ein Deadlock
entdeckt wird, rollt man einen der Prozessen der eines beteiligten Betriebsmittel anfordert zu seinem
letzten Checkpoint zurück.
Recovery through Killing. Die einfachste Methode ist es einen der am Deadlock beteiligten Prozesse
zu killen. Wenn der Deadlock dadurch nicht behoben wird, killt man weitere Prozesse. Alternativ
kann man auch nicht am Deadlock beteiligte Prozesse killen. In der Praxis geht das natürlich
schlecht, da dadurch Daten verloren gehen. Ein Beispiel wo es funktioniert sind Transaktionen in
Datenbanken.
6.3.4
Wie funktioniert Deadlock-Vermeidung?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
69
Kapitel 6. Betriebssysteme
Bei der Deadlock-Vermeidung versucht man zu verhindern, dass ein Prozess in einen unsicheren Zustand
kommt. In der Praxis ist dies selten anzuwenden, da man dafür die zukünftigen Ressourcenbedarf der
Prozesse kennen muss. Ein Beispiel ist der Bankiersalgorithmus.
6.3.5
Wie funktioniert Deadlock-Verhinderung?
Man versucht eine der vier Deadlock-Bedingung generell auszuschliessen.
1. Mutual exclusion condition. Mann kann wie im Falle des Druckers einen Spooler einrichten. Dadurch hat nur noch ein einziger Prozess Zugriff auf ein Betriebsmittel. Das Problem ist, dass man
nicht alle Betriebsmittel spoolen kann, z. B. die Prozesstabelle. Ausserdem können sich dadurch
neue potentielle Deadlocks ergeben. Der Printspooler braucht Plattenspeicher, auch dieser kann
deadlocken.
2. Hold and wait condition. Man könnte Prozesse zwingen alle ihre Betriebsmittel auf einen Schlag
anzufordern, dies geht aber meist nicht, da die Prozesse zu Beginn noch nicht wissen, welche Betriebsmittel sie benötigen. In bestimmten Fällen funktioniert kann das sehr gut funktionieren.
Datenbanken setzen Two-Phase Locking ein, was im Prinzip diesem Ansatz entspricht.
3. No preemption condition. Das geht mit vielen Betriebsmittel einfach nicht anders.
4. Circular wait condition. Eine Möglichkeit ist den Betriebsmittel eindeutige Nummern zuzuordnen
und Prozessen das Anfordern von Betriebsmittel nur in numerischer Reihenfolge zu erlauben. Dadurch können keine Zyklen im Betriebsmittelgraphen und damit auch keine Deadlocks entstehen.
Das Problem ist, dass es in einem echten System fast unmöglich ist, eine vernünftige Nummerierung
aller Betriebsmittel zu finden.
6.3.6
Was sind die Bedingungen für einen Deadlock?
Damit ein Deadlock eintreten kann, müssen die folgende vier Bedingungen gelten.
1. Mutual exclusion condition. Jedes Betriebsmittel ist entweder genau einem Prozess zugeordnet oder
frei.
2. Hold and wait condition. Ein Prozess der bereits Betriebsmittel besitzt kann weitere anfordern.
3. No preemption condition. Betriebsmittel können Prozessen nicht weggenommen werden. Die Prozesse müssen die Betriebsmittel freiwillig abgeben.
4. Circular wait condition. Es gibt eine kreisförmige Kette mit zwei oder mehr Prozessen, die jeweils
auf ein Betriebsmittel warten, das vom nächsten Nachbarn der Kette belegt wird.
6.3.7
Was sind sichere Zustände?
Eine Zustand ist sicher, wenn er nicht in einem Deadlock ist und es eine Scheduling Reihenfolge gibt, so
dass alle Prozesse abgearbeitet werden können, selbst dann wenn alle Prozesse plötzlich die Maximale
Anzahl an Betriebsmittel fordern.
6.3.8
Was ist der Bankiersalgorithmus?
Der Bankiersalgorithmus verwendet das Prinzip der Verklemmungsvermeidung. Bei einer Anfrage eines
Kunden wird der Betrag probeweise zugeteilt und dann überprüft der Algorithmus, ob in der entstehenden Situation einen Verklemmung möglich ist, wenn ja, verweigert er die Geldausgabe. Dafür ist aber
nötig, dass der Algorithmus die zukünftigen Anforderungen der Prozesse (Kunden) abschätzen kann
(Kreditrahmen).
6.3.9
Was ist ein Betriebsmittelgraph?
Mit einem Betriebsmittelgraph lässt sich graphisch darstellen welche Prozesse welche Betriebsmittel
belegen und welche Prozesse welchen Betriebsmittel anfordern.
70
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.4. Speichermanagement
6.4
Speichermanagement
6.4.1
Was ist ein virtueller Speicher?
Virtueller Speicher ist Speicher der Programmen voll zur Verfügung steht, der aber grösser als der
tatsächlich vorhandene, physische Speicher ist.
6.4.2
Welche Verfahren zur Seitenersetzung kennen Sie?
Optimaler Algorithmus. Der optimale Algorithmus ist ein in der Praxis nicht umsetzbarer Algorithmus der aber zur Qualitätsbeurteilung von echten Algorithmen benutzt wird.
Algorithmus. Wenn eine Page Fault auftritt liegt eine bestimmte Anzahl von Seiten im Speicher.
Jeder dieser Seiten kann (theoretisch) eine Zahl zugeordnet werden, die der Anzahl der Instruktionen, die vergehen, bis diese Seite benutzt wird, entspricht. Der optimale Algorithmus entfernt die
Seite mit der höchsten Zahl, deren Benutzung also am weitesten in der Zukunft liegt.
Vor- und Nachteile. Es liegt auf der Hand, dass dieses Verhalten optimal aber nicht realisierbar ist.
NRU. Der Not Recently Used Algorithmus teilt Seiten entsprechende ihrer Reference- und ModifiedBits in Klassen ein und wählt eine möglichst lange nicht benutzte Seite.
Algorithmus. In den meisten Systemen gibt es Reference- und dein Modified-Bit. Falls dein Page
Fault auftritt, teilt der Algorithmus die Seiten in vier Gruppen ein
Class
Class
Class
Class
0:
1:
2:
3:
not referenced, not modified
not referenced, modified
referenced, not modified
referenced, modified
Nun entfernt der Algorithmus zufällig eine Seite aus der Klasse mit der niedrigsten Zahl. Vor- und
Nachteile. Es werden keine Seiten, die stark benutzt werden, entfernt und die Implementierung ist
einfach. Die Leistung des Algorithmus ist nicht wirklich optimal.
FIFO. Einfaches FIFO-Prinzip.
Algorithmus. Die Seiten werden in einer Queue verwaltet, falls ein Page Fault auftritt, wird die
älteste Seite entfernt und die Neue an das Ende der Queue angehängt.
Vor- und Nachteile. Die Implementierung ist sehr einfach aber das Problem ist, dass die älteste
Seite nicht unbedingt auch eine Seite ist, die selten genutzt wird.
Second Chance. Second Chance ist eine Erweiterung von FIFO die das Reference-Bit mit in die
Entscheidung einbezieht.
Algorithmus. Falls ein Page Fault auftritt geht der Algorithmus erst mal so vor wie FIFO und betrachtet den Kopf der Liste. Falls die das Reference-Bit der Seite am Kopf der Queue nicht gesetzt
wird, wird sie entfernt. Falls es gesetzt ist, bekommt sie eine zweite Chance und wird an das Ende
der Queue gehängt und der Algorithmus schaut sich die zweit-älteste Seite an.
Vor- und Nachteile. Ein Problem von Second Chance ist, dass es, wenn bei allen Seiten das
Reference-Bit gesetzt ist, zu FIFO degenerieren kann. Das andere Problem ist, dass das ständige
Umhängen von Seiten in der Queue aufwendig ist.
Clock. Clock ist nur eine bessere Implementierung von Second Chance.
Algorithmus. Bei Clock sind die Seiten in einer kreisförmigen Liste wie bei einer Uhr angeordnet.
Ein Zeiger zeigt auf die älteste Seite. Wenn nun ein Page Fault auftritt, prüft der Algorithmus ob
das Reference-Bit der ältesten Seite gesetzt ist. Wenn nicht, wird die Seite ersetzt. Falls es gesetzt
ist, wird es gelöscht und der Zeiger eine Position weiter gestellt.
Vor- und Nachteile. Dieser Algorithmus behebt die Implementierungsprobleme von Second Chance
und stellt einen realistischen Algorithmus dar.
LRU. Der Least Recently Used Algorithmus entfernt immer die Seite, die am längsten nicht benutzt
wurde.
Algorithmus. Man nimmt an, dass Seiten in letzter Zeit stark benutzt wurden, wohl auch in Zukunft noch benutzt werden, deshalb möchte man die am längsten nicht benutzte Seite entfernen.
Grundsätzlich könnte der Algorithmus mit einer Liste, die immer so organisiert wird, dass die am
längsten nicht genutzte Seite am Ende steht, realisiert werden. Dies ist aber sehr aufwendig. Mit
ein bisschen zusätzlicher Hardware geht es deutlich einfacher. Dazu benötigt man einen Counter
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
71
Kapitel 6. Betriebssysteme
der nach jeder Instruktion erhöht wird, ausserdem muss der Seitentabelleneintrag ein Feld haben
um einen Counterwert aufzunehmen. Bei jedem Speicherzugriff wird der aktuelle Counterwert in
dem entsprechenden Seitentabelleneintrag gespeichert. Falls ein Page Fault auftritt, wird die Seite
mit dem niedrigsten Counterwert entfernt. Eine andere Hardwareimplementierung verwendet eine
Matrix zur Speicherung derselben Information.
Vor- und Nachteile. Sehr guter Algorithmus, der aber Unterstützung der Hardware erfordert.
NFU. Not Frequently Used ist ein einfacher Versuch LRU mit Software zu simulieren.
Algorithmus. NFU verwendet einen Software-Counter für jede Seite der beim Einlagern der Seite
auf 0 gesetzt wird. Bei jedem Clocktick durchläuft das Betriebssystem alle Seiten und addiert den
Wert des Reference-Bits auf den Counter. Falls ein Page Fault auftritt, wird die Seite mit dem
niedrigsten Counterwert entfernt.
Vor- und Nachteile. Das Hauptproblem ist, dass NFU niemals etwas vergisst. Seiten die vergangener
Zeit extrem häufig benutzt wurden, haben einen hohen Counterwert und verlieren diesen nicht mehr,
auch wenn sie später gar nicht mehr benutzt werden.
Aging. Aging ist eine kleine Modifikation von NFU die den Algorithmus sehr nah an LRU bringt.
Algorithmus. Wieder hat jede Seite einen eigenen Counter. Diesmal wird der Counterwert bevor
das Reference-Bit addiert wird um ein Bit nach rechts verschoben. Ausserdem wird der Wert nicht
auf das Bit am weitesten rechts, sondern auf das Bit am weitesten links, addiert. Wenn ein Page
Fault auftritt wird die Seite mit dem kleinsten Counterwert entfernt. Eine Seite die lange nicht
benutzt wurde, hat viele führende Nullen und damit einen kleinen Wert.
Vor- und Nachteile. Dieser Algorithmus nähert LRU recht gut, verhält sich in zwei Punkten aber
doch unterschiedlich. Da pro Intervall von Clocktick zu Clocktick nur ein Bit gespeichert wird,
kann man nicht zwischen unterschiedlichen Zeitpunkten in einem Intervall speichern. Der andere
Unterschied ist auf die endliche Anzahl von Bits in den Countern zurückzuführen. Falls zwei Seiten
beide den Counter-Wert 0 haben, hat man keine Möglichkeit zu beurteilen, welche älter ist. In
der Praxis sind 8 Bits aber meist ausreichend da damit bei einem Clocktick-Intervall von 20ms ein
Zeitraum von 160ms überwacht werden kann.
Working Set. Alle bisher beschriebenen Algorithmen verwenden die Strategie des Demand Paging.
Ein Prozess wird zuerst ohne seine Seiten gestartet, die benötigten Seiten werden dann Stück für
Stück on demand eingelagert. Reale Programme haben meist bestimmte Lokalitätseigenschaften.
D. h. sie greifen während einer bestimmten Phase meist nur auf wenige ihrer Seite zu. Die Menge der
Seiten, die ein Prozess gerade benutzt, nennt man das Working Set. Bei den bisher aufgeführten
Ersetzungsstrategien, treten sehr viele Page Faults auf, bis das Working Set eines Prozesses im
Speicher ist. Beim Mehrprogrammbetrieb werden Prozesse oft komplett aus dem Speicher entfernt.
Die Idee ist nun dem Prozess, bevor er wieder gestartet wird, sein Working Set zur Verfügung
zu stellen. Diese Information muss vor dem Verdrängen des Prozesses gespeichert werden. Das
Einlagern der Seiten bevor der Prozess anläuft, wird als Prepaging bezeichnet.
Algorithmus. Wenn die Information über das Working Set eines Prozesses bekannt ist, kann man
daraus auch einen effizienten Seitenersetzungsalgorithmus ableiten. Falls ein Page Fault auftritt,
sollte eine Seite entfernt werde, die nicht Teil des Working Sets ist. Das Merken des Working Sets ist
sehr aufwendig, daher gibt es verschiedene Näherungslösungen. Eine besteht darin sich zu merken
welche Seiten der Prozess in den letzten τ Sekunden benutzt hat. Die CPU-Zeit die ein Prozess seit
seinem Start tatsächlich benutzt hat, nennt man current virtual time. Der Ersetzungsalgorithmus
arbeitet wie folgt. Wie immer ist in den Seitentabelleneinträgen das Reference-Bit gespeichert.
Zusätzlich hat jeder Eintrag noch ein Feld in dem die Zeit gespeichert wird, wann die Seite zuletzt
benutzt wurde. Bei jedem Clocktick wird das Reference-Bit gelöscht. Falls nun ein Page Fault
auftritt, wird die ganze Seitentabelle durchlaufen und wie folgt vorgegangen. Ist das Reference-Bit
gesetzt, wird die aktuelle Zeit im Eintrag gespeichert, dadurch wird gekennzeichnet, dass die Seite
benutzt wurde, als der Page Fault auftrat. Da diese Seite benutzt wurde, gehört sie zum Working
Set und sollte nicht entfernt werden. Falls das Reference-Bit 0 ist, wurde die Seite nicht benutzt
und stellt eine Kandidaten für die Auslagerung dar. Jetzt wird zuerst ihr Alter berechnet, (current
virtual time minus Zeit der letzten Benutzung). Falls das Alter grösser als τ ist, gehört die Seite
nicht mehr zum Working Set und wird ersetzt. Falls ihr Alter kleiner als τ ist, gehört die Seite
zum Working Set und wird verschont. Man merkt sich aber die Seite mit dem grössten Alter. Falls
sich beim Durchlauf rausstellt, dass alle Seiten zum mit gelöschten Reference-Bit zum Working Set
gehören, wird die mit dem höchsten Alter entfernt. Falls bei allen Seiten das Reference-Bit gesetzt
72
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.4. Speichermanagement
ist, wird eine Seit ausgelost (am besten eine saubere).
Vor- und Nachteile. Der Algorithmus ist sehr gut, aber aufwendig zu implementieren. Ausserdem
muss immer die komplette Seitentabelle durchlaufen werden.
WSClock. Dieser Algorithmus ist eine vereinfachte Implementierung des Working Set Algorithmus
der die Idee des Clock Algorithmus’ aufgreift.
Algorithmus. Wieder wird pro Seitentabelleneintrag das Reference-Bit, das Modified-Bit und die
Zeit des letzten Zugriffs gespeichert. Diesmal werden die Einträge in eine kreisförmigen Liste gespeichert und es gibt einen Zeiger der auf einen der Einträge zeigt. Zuerst wird wieder das Reference-Bit
getestet. Ist es gesetzt wurde diese Seite kürzlich benutzt und sollte nicht entfernt werden. Der
Algorithmus löscht das Reference-Bit und geht zur nächsten Seite. Wenn er dort eine Seite, deren
Reference-Bit nicht gesetzt ist, vorfindet, geht er wie folgt vor. Ist das Alter dieser Seite grösser als τ
gehört sie nicht zum Working Set. Falls sie dazu auch noch sauber ist, wird sie einfach ersetzt. Falls
sie nicht sauber ist, kann sie nicht einfach ersetzt werden. Um einen Prozesswechsel zu vermeiden,
wird sie nicht direkt auf die Platte geschrieben, sondern der Schreib-Auftrag wird geschedult und
der Zeiger auf die nächste Seite gesetzt. Es könnte ja sein, dass sich noch eine alte, saubere Seite
findet. Was passiert nun, wenn der Algorithmus einmal alle Seiten durchlaufen hat ohne eine alte,
saubere Seite zu finden. Jetzt müssen zwei Fälle unterschieden werden
1. mindestens ein Schreib-Auftrag wurde geschedult
2. kein Schreib-Auftrag wurde geschedult
Im ersten Fall macht der Algorithmus einfach weiter, früher oder später findet er eine alte, saubere Seite, da der Schreib-Auftrag irgendwann ausgeführt wird. Im zweiten Fall befinden sich alle
Seiten im Working Set, sonst währe ein Schreib-Auftrag abgegeben worden. Jetzt sucht sich der
Algorithmus einfach eine saubere Seite und ersetzt sie (die Position einer sauberen Seite kann er
sich während des Durchlaufs merken). Falls es keine saubere Seite gibt, dann hilft alles nichts, die
aktuelle Seite wird geschrieben und ausgetauscht.
Vor- und Nachteile. Wegen der recht einfachen Implementierung und der guten Performance, wird
WSClock in der Praxis häufig eingesetzt.
6.4.3
Was ist Fragmentierung?
Man unterscheidet zwischen interner und externer Fragmentierung.
Interne Fragmentierung. Im Zusammenhang mit Paging spricht man von interner Fragmentierung. Damit ist die Speichervergeudung gemeint, wenn Seiten nur halb belegt werden. Die interne
Fragmentierung spricht für eine kleine Seitengrösse, es gibt aber auch Argumente für grosse Seitengrössen.
Externe Fragmentierung. Im Zusammenhang mit Segmentierung spricht man von externer Fragmentierung. Hiermit ist das über die Dauer entstehende Muster aus belegtem Speicher und Löcher
gemeint, das beim Ein- und Auslagern von Segmenten entsteht. Mit Compaction kann man die
Löcher wieder zu einem einzigen grossen Loch zusammenfassen, was aber sehr aufwendig ist.
6.4.4
Was ist Paging?
Von Paging spricht man, wenn Prozess nicht unbedingt komplett, sondern auch teilweise im Speicher
gehalten werden können.
6.4.5
Was ist Swapping?
Von Swapping spricht man, wenn jeder Prozess immer komplett in den Speicher geladen wird. Beim
Prozesswechsel wird der Prozess (und alle zugehörigen) Daten auf die Platte ausgelagert und der neue
Prozess eingelagert.
6.4.6
Welche Programmierschnittstelle bietet die Speicherverwaltung an?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
73
Kapitel 6. Betriebssysteme
Die meisten Betriebssysteme stellen den Userprozessen Systemaufrufe zum Anfordern und Freigeben
von Speicher zur Verfügung. Bei Unix heisst der Befehl zur Veränderung der Grösse des Datensegmentes
brk. Zusätzlich gibt es meist noch Befehle um Memory-Mapped Files einzurichten.
Die Verwaltung des virtuelle Speichers sollte für Prozesse und Programmierer transparent sein. Ein
Ausnahme ist der Einsatz von Shared Memory. Wollen sich zwei Prozesse zum schnellen Austausch von
Daten Speicher teilen, muss die Programmierschnittstelle der Speicherverwaltung Funktionen anbieten,
damit Prozesse solche gemeinsamen Speicherbereiche einrichten können, z. B. Memory-Mapped Files.
Windows bieten auch einige Funktionen an um das Paging zu kontrollieren, so kann man z. B. für eine
bestimmten Speicherbereich das Paging ganz ausschalten.
6.4.7
Wie erkennt man, dass auf eine Seite zugegriffen wurde?
Im Seitentabelleneintrag gibt es ein Reference-Bit. Diese wird gesetzt sobald auf die Seite zugegriffen
wird.
6.4.8
Ist die MMU ein Teil des Betriebssystems?
Nein. Sie ist heute meist Teil der CPU, kann bei älteren Systemen aber auch ausserhalb der CPU sein.
6.4.9
Welche Speicher-Einlagerungsstrategien kennen Sie?
On-Demand. Alle Seitenersetzungsstrategien ausser den auf Working Sets basierenden, verwenden
diese Strategie. Seiten werden dann eingelagert, wenn sie das erste Mal gebraucht werden.
Prepaging. Wenn die Working Set Information bekannt ist, kann das Working Set eines Prozesses
eingelagert werden, bevor er gestartet wird.
6.4.10
Was ist ein Working Set?
Die Menge der Seiten, die ein Prozess gerade benutzt, nennt man das Working Set.
6.4.11
Was ist das Buddy Verfahren?
Das Buddy-Verfahren wird von Linux zur Speicherverwaltung eingesetzt. Falls ein Stück Speicher
benötigt wird, wird die Grösse des Stücks zuerst auf eine Potenz von 2 aufgerundet und dann im
Speicher vorhandene Löcher solange halbiert bis es genau passt. Werden zwei nebeneinander liegende
Speicherbblöcke (Buddies) frei, werden sie wieder zusammengefasst.
6.5
I/O
6.5.1
Welche Schichten hat die E/A-Verwaltung?
User-level I/O Software
Device-independent OS software
Device drivers
Interrupt handler
Hardware
6.6
Betriebssystem-Design
6.6.1
Was ist ein Microkernel?
74
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.6. Betriebssystem-Design
Die Idee eines Microkernels ist es nur minimale Funktionalität in den Kernel einzubauen um die Effizienz und Zuverlässigkeit zu steigern. Zum Beispiel werden das Dateisystem und das Speichermanagement in Userprozesse ausgelagert. Durch die Modulare Struktur sind Microkernel-Systeme deutlich
übersichtlicher und daher besser wartbar. Die viele Funktionen in Userprozesse ausgelagert sind, sind
sie stabiler. Das abstürzen eine Userprozesses reisst den Kernel normalerweise nicht mit. Durch die
mit der Modularisierung verbundenen häufigen Wechsel zwischen User- und Kernelprozessen ist die
Performance von Microkernelsystemen etwas schwächer. Mach und Minix sind Microkernelsysteme.
6.6.2
Was bedeutet monolithisch?
Eine monolithische Struktur ist das genau Gegenteil eines Microkernels. Bei monolithischen Systemen
steckt alle betriebssystemrelevante Funktionalität im Kernel.
6.6.3
Welche Funktionen beinhaltet ein Microkernel?
Scheduling
6.6.4
Was gehört zum einem Betriebssystemkern?
Das kommt auf die Struktur des Systems an, Microkernel oder monolithisch. Was immer drin ist, ist
der Scheduler.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
75
Kapitel 6. Betriebssysteme
6.7
Beispiele
6.7.1
Erklären Sie doch mal die Unterschiede zwischen Unix und Windows 2000.
Unix/Linux
Windows
Grösse (LOC)
Struktur
Linux 2.2: 1 M, Solaris 5.8: 2 M
Die Struktur hängt von der jeweiligen Unix-Version
ab. So hat MINIX z. B. eine Microkernel, Linux
dagegen ist monolithisch.
Schnittstelle
Unter Unix rufen Prozessen direkt die System Calls
auf. Diese werden über Bibliotheken zur Verfügung
gestellt.
Prozesse können bei Linux generell nur durch forken eines Prozesses erzeugt werden. Dadurch entsteht eine Prozesshierarchie. Die Unixprozesse entsprechen fast genau den Prozessbegriff wie er z. B.
im Tanenbaum verwendet wird. Ein Prozess hat
einen Thread of Control und ihm sind Ressourcen
aller Art zugeordnet.
29 M
Ab Version 4.0 ist NT absolut monolithisch, vorher
war es zwar auch kein Microkernel, aber es waren
doch einige Betriebssystemfunktionen in Userprozesse ausgelagert.
Windows versteckt die eigentlichen System Calls
hinter einer schwergewichtigen API mit enormen
Funktionsumfang.
Eine Prozesshierarchie gibt es Windows nicht.
Windows führt einige Begriffe ein. Ein Job ist
eine Sammlung von Prozessen, zu jedem Prozess
gehören einer oder mehr Threads. Prozesse stellen eher eine Verwaltungseinheit dar, ihnen fehlt
eigentlich der Thread of Control. Auf Userebene
kann ein Thread mehrere Fibers, leichtgewichtige
Threads enthalten.
Auch Windows verwendet Round-Robin Scheduling
mit dynamischen Prioritäten wobei Prozesse die
Prioritäten ihrer Threads beeinflussen können. Das
Windows Scheduling basiert auch nur auf Threads.
Fibers können nur von Prozessen selbst geschedult
werden.
Jedem Prozess stehen 4GB Speicher zur Verfügung
wobei in die oberen zwei GB bei jedem Prozesse das Betriebssystem eingeblendet ist, das aber
geschützt ist. Das liegt daran, dass bei Windows
bei einem Wechsel vom User- zum Kernelmodus
der selbe Prozess (Thread) weiter läuft. Ein Pagingdaemon versucht kontinuierlich den Speicher
möglichst frei zu halten. Der verwendete Ersetzungsalgorithmus basiert auf einem Working Set.
Windows verwendet aber kein Prepaging.
Windows bietet diverse Möglichkeiten zur Kommunikation, darunter Pipes, Named Pipes, Mailslots,
Sockets, RPC und Shared Files.
Prozesse
Scheduling
Unix und Linux verwenden Round-Robin Scheduling mit dynamischen Prioritäten. Das Linux Scheduling basiert auf Threads.
Speicher
Das Paging wird bei Unix von einem PagingDaemon durchgeführt der eine modifizierte Variante des Clock-Algorithmus’ einsetzt. Linux verwendet den Buddy-Algorithmus und ebenfalls einen
Clock-ähnlichen Ersetzungsalgorithmus. Es gibt
keine Working Set Verwaltung und kein Prepaging.
IPC
Prozesskommunikation läuft bei Unix vorwiegend
über Pipes, die eine Form des Nachrichtenaustausches darstellen. Zusätzlich können Prozesse über
Signale kommunizieren (siehe 6.7.3).
Unix ordnet jedem Benutzter eine UID dar und organisiert die Benutzter in Gruppen. Dateien werden die bekannten Rechte entsprechend der Userund Gruppen-ID zugeordnet. Durch das Everything is a File-Konzept lässt sich dieses Prinzip
z. B. auch auf Ein- und Ausgabe anwenden.
Unix folgt dem Everything is a File-Konzept.
Sicherheit
Misc
76
Windows wird jeder Benutzter und jede Gruppe
durch eine eindeutige Security ID (SID) identifiziert. Jeden Objekt kann eine ACL (siehe 3.5.4)
zugeordnet werden, die dem User entsprechende
Operation auf einem Objekt gestattet.
Bei Windows ist alles ein Objekt.
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
6.7. Beispiele
6.7.2
Hat Windows 2000 einen Microkernel?
In den ersten Versionen hatte NT zwar einen rechten schlanken Kernel, da er aber Speichermanagement,
Dateisystem u. Ä enthielt, konnte man nicht von einem Microkernel sprechen. Seit der Version 4.0 steckt
ein Grossteil der Funktionalität im Kernel, also erst recht kein Microkernel.
6.7.3
Was für Möglichkeiten bietet Unix zur Prozesskommunikation?
Pipes. Pipes stellen eine Form von Kommunikation über Nachrichten da. Zwischen zwei Prozessen kann ein Kanal angelegt werden. Jeder der Prozesse kann einen Datenstrom in diesen Kanal
schicken. Diese Kanäle heissen Pipes.
Software Interrupts. Prozesse können Signale an andere Prozesse verschicken. Die Prozesse können
dem System mitteilen wie es mit eingehenden Signalen umgehen soll. Dazu muss ein Prozess ein
Signalbehandlungsroutine angeben. Falls ein Signal eingeht, wird diese Routine sofort gestartet.
Signale können nur an Prozesse aus der eigenen Prozessgruppe (die Verwandten) geschickt werden.
Signal werden auch für andere Zwecke benutzt, so bekommt ein Prozess der durch 0 teilt ein SIGFPE
Signal geschickt.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
77
Kapitel 7
Rechnernetze
7.1
Allgemeines
7.1.1
Wozu verwendet man Codierungen?
Codierung dient dazu, den Inhalt einer Nachricht in einer speicherbaren, verarbeitbaren und übermittelbaren Form darzustellen.
7.1.2
Welche Fehler treten in Netzwerken auf?
Daten können kaputt gehen
Daten können verloren gehen
Daten können in der falschen Reihenfolge ankommen
Leitungen können ganz zusammenbrechen
7.1.3
Wie kann man Fehler erkennen?
Das hängt von der Art der Fehler ab. Störungen innerhalb eines Frames können durch Prüfsummen erkannt werden. Verloren gegangene Frames können durch Bestätigungen erkannt werden. Flusskontrolle
stellt die richtige Reihenfolge sicher.
7.1.4
Unterschiede zwischen verbindungsorientierter und verbindungsloser Kommunikation?
Bei verbindungsorientierter Kommunikation muss der Sender zum Empfänger eine (virtuelle) Verbindung aufbauen, erst dann kann der Daten senden. Danach wird die Verbindung wieder abgebaut. Eine
Verbindung wird als eine sichere Kommunikation betrachtet. Normalerweise geht man davon aus, dass
die Daten bei Empfänger in der selben Reihenfolge ankommen, wie sie vom Sender verschickt wurden.
Dies ist bei verbindungsloser Kommunikation nicht sicher gestellt. Bei verbindungsloser Kommunikation
sendet der Sender einfach darauf los. Die Daten kommen beim Empfänger an oder auch nicht.
7.1.5
Was ist ein Multicast?
Bei einem Multicast kann eine Station an eine Gruppe von Empfänger eine Nachricht verschicken. Dies
muss unterschieden werden vom Broadcast, wo eine Station an alle anderen Stationen eine Nachricht
schickt.
7.1.6
Was sind LAN, MAN und WAN?
Name
Distanzen
Beispiel
Technologien
LAN
MAN
WAN
Local Area Network
< 1km
Büro
Ethernet, WLAN
Metropolitan Area Network
1 km – 10 km
Stadt
Cable, FDDI
Wide Area Network
> 10 km
Land
ATM
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
79
Kapitel 7. Rechnernetze
7.2
ISO–OSI–Referenzmodell
7.2.1
i Gegen Sie eine Kurzeinführung in das ISO–OSI–Schichtenmodell.
1. Physical Layer (Physische Schicht).
Die physische Schicht ist dafür zuständig rohe Bits über den Kommunikationskanal zu schicken.
Hier geht es um mechanische und elektrische Fragen, ausserdem spielt das Timing eine wichtige
Rolle. Die Implementierung ist meist stark von dem darunter liegenden Leiter abhängig.
Dienste. SendFrame und RecieveFrame
Protokolle.
Stichworte. Twisted Pair, Glasfaser, Funk, Satellit, Manchester-Codierung
2. Data Link Layer (Sicherungsschicht).
Die Sicherungsschicht berücksichtigt, dass die von der physischen Schicht gelieferten Bitströme mit
Fehler behaftet sein können. Sie ist für Fehlerkontrolle und Korrektur zuständig. Ausserdem teilt
die Sicherungsschicht die zu übertragenden Daten in sog. Frames auf. Desweiteren findet hier
die Flusssteuerung statt. Bei Netzen mit Vielfachzugriffsmedien gibt es noch eine Teilschicht, die
MAC-Layer, die für die Medienzugriffskontrolle sorgt.
Dienste. SendPacket, RecievePacket
Protokolle. HDLC, SLIP, PPP
Stichworte. Sliding Window, Bit-Stuffing
3. Network Layer (Netzwerkschicht).
Die Netzwerkschicht muss Pakete von der Quelle zum Ziel versenden können. Der Weg verläuft
normalerweise über mehrere Router, deshalb findet das Routing auf der Netzwerkschicht statt. Die
Netzwerkschicht stellt somit die erste Ende-zu-Ende Übertragungschicht dar, die Sicherungsschicht
überträgt die Daten nur von einem Ende des Leiters zum anderen. Ausserdem werden Stauprobleme
in Netzwerken in der Netzwerkschicht gelöst (und in der Transportschicht).
Dienste. SendTPDU, RecieveTPDU
Protokolle. IP, ARP, DHCP
Stichworte. Staukontrolle, Routing, IP
4. Transport Layer (Transportschicht).
Die Aufgabe der Transportschicht ist es einen zuverlässigen, kostengünstigen Transport von der
Quelle vom Ziel anzubieten. Dieser Transport muss unabhängig von der physischen Struktur der
Netzwerke die dazu dienen, sein. Manchmal werden die Schichten in zwei Teile zerlegt, die unteren
vier Schichten betrachtet man als den Transport Service Provider und die oberen Schichten als den
Transport Service User. Die Transportschicht stellt somit die Schnittstelle zwischen Anbieter und
Nutzer da, deshalb spielt sei eine besondere Rolle.
Dienste. Connect, SendData, RecieveData, Disconnect
Protokolle. TCP, UDP
Stichworte. Sliding Window, Three-Way Handshake
5. Session Layer (Sitzungsschicht).
Die Sitzungsschicht erlaubt es Benutzern an verschiedenen Maschinen Sitzungen zwischen ihnen
aufzubauen. Eine Sitzung ermöglicht gewöhnlichen Datentransport, wie die Transportschicht auch,
bietet aber zusätzliche Dienste, die für bestimmte Anwendungen wichtig sind.
Die Sitzungsschicht existiert im TCP/IP-Modell nicht und ist logisch schlecht von der Anwendungsschicht trennbar.
6. Presentation Layer (Darstellungsschicht).
Die Darstellungsschicht führt bestimmte Funktionen aus, deren häufige Verwendung eine allgemeine Lösung rechtfertigen. Die Darstellungsschicht kümmert sich auch um Syntax und Semantik der
übertragenen Information.
Die Darstellungsschicht existiert im TCP/IP-Modell nicht und ist logisch schlecht von der Anwendungsschicht trennbar.
Protokolle. MIME
7. Application Layer (Anwendungsschicht).
In der Anwendungsschicht sind viele bekannte Protokolle wie HTTP angesiedelt.
Protokolle. HTTP, FTP, SNMP, SMTP
80
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.2. ISO–OSI–Referenzmodell
Host A
7
Application
Application
Presentation protocol
6 Presentation
5
Host B
Application protocol
Presentation PPDU
Session protocol
Session
APDU
Session
SPDU
Transport
TPDU
Transport protocol
4
Transport
Router
Router
3
Network
Network
Network
Network
Paket
2
Data link
Data link
Data link
Data link
Frame
1
Physical
Physical
Physical
Physical
Medium
Medium
Bit
Medium
Die Darstellung zeigt das ISO-OSI-Schichtenmodell. Wichtig sind die folgenden Begriffe
Dienst (Service). Ein Dienst ist eine Menge von Operationen die eine Schicht der Schicht über ihr
anbietet. Es wird nichts über die Implementierung dieser Operationen ausgesagt.
Dienstprimitive. Die Dienstprimitive sind die Operation (Methoden), die eine Schicht der Schicht
über ihr anbietet. Es herrscht einige Verwirrung darüber welche Schicht nun welche Primitive
hat. Zum Beispiel wird manchmal behauptet, die Schicht 1 hätte die Primitiven SendBit und
RecieveBit. Das stimmt so nicht. Das sind nämlich genau die Primitiven des Leiters und nicht
der Schicht 1.
Protokoll. Protokolle definieren Regel für die Nachrichten die zwischen Instanzen der selben Schicht
ausgetauscht werden. Zwei Instanzen auf der selben Schicht können, wenn Sie wollen sich für ein
neues Protokoll entscheiden. Solange sie ihre Dienste nicht ändern, wird das Netz davon nicht
beeinflusst.
7.2.2
Was sind die Anforderungen an die einzelnen Schichten?
siehe 7.2.1.
7.2.3
Nennen Sie für jede Schicht ein Beispielprotokoll.
siehe 7.2.1.
7.2.4
Wer hat das OSI-Schichtenmodell entworfen?
Das OSI-Modell basiert auf einem Vorschlag der von der ISO ausgearbeitet wurde.
7.2.5
Warum vertikale und nicht horizontale Einteilung?
Mit vertikaler Einteilung wird ein Schichtenmodell impliziert, siehe 7.2.8. Horizontale Einteilung entspricht einer Partitionierung mit komplizierteren Abhängigkeiten.
7.2.6
Was bedeutet das Open ins OSI?
Unter Open Systems versteht man Systeme die für die Kommunikation mit anderen Systemen offen
sind.
7.2.7
Unterschied zwischen ISO–OSI–Referenzmodell und Schichtenmodell des Internet?
Das TCP/IP-Modell spezifiziert weder Schicht 1 noch Schicht 2. Ausserdem nimmt es oberhalb der
Schicht 4 keine Trennung mehr vor. Die Darstellung zeigt die beiden Modelle.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
81
Kapitel 7. Rechnernetze
OSI
7 Application
6 Presentation
5
Session
4
Transport
3
Network
2
Data link
Physical
1
7.2.8
TCP/IP
Application
Transport
Network
Host-tonetwork
Was für einen Sinn hat das Schichtenmodell?
Reduzierung der Komplexität und Austauschbarkeit.
7.2.9
Was ist ein SAP?
Ein SAP ist ein Service Access Point oder ein Dienstzugriffspunkt. Dies ist der Punkt in dem die Schicht
n der Schicht n + 1 ihre Dienste zur Verfügung stellt.
7.3
Schichtübergreifend.
7.3.1
Auf welcher Schicht ist ein Hub angesiedelt?
Physische Schicht.
7.3.2
Auf welcher Schicht ist ein Switch angesiedelt?
Sicherungsschicht.
7.3.3
Auf welcher Schicht ist eine Bridge angesiedelt?
Sicherungsschicht.
7.3.4
Auf welcher Schicht ist ein Router angesiedelt?
Netzwerkschicht.
7.3.5
Beschreiben Sie Ethernet.
Ethernet ist eine LAN-Technologie, die durch IEEE 802.3 standardisiert ist und eine Übertragungsrate
von 10 MBit/s bietet. Ethernet kann mit Coax, Twisted-Pair und Glasfaser eingesetzt werden. Es
handelt sich um ein Broadcastnetz, dass CSMA/CD als Zugriffsverfahren einsetzt und die ManchesterCodierung verwendet. Als Adressen verwendet Ethernet die weltweit eindeutigen 48 Bit MAC Adressen.
Ethernet selbst bietet nur verbindungslose Kommunikation ohne Bestätigung. Es kann aber durch die
Logical Link Control (LLC)-Schicht erweitert werden, die auch verbindungsorientierte Kommunikation
erlaubt. Dann ist die Sicherungsschicht in zwei Schichten, die MAC-Schicht und die LLC-Schicht zerlegt.
Die Medium Access Control (MAC)-Schicht beinhaltet das Vielfachzugriffsverfahren. Die Logical Link
Control (LLC)-Schicht bietet die verbindungsorientierte Kommunikation, die LLC ist durch IEEE 802.2
definiert. Ethernet ist sehr einfach und günstig und daher sehr weit verbreitet. Dies gilt insbesondere,
da auch schnellere Varianten von Ethernet, Fast Ethernet und Gigabit Ethernet mit 100 bzw. 1000
MBit/s existieren.
7.3.6
Was wissen Sie über TCP/IP
siehe 7.7.12 und 7.8.3.
82
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.4. Schicht 1
7.4
Schicht 1
7.4.1
Was gibt es für Medien?
Kabel
Coax
Twisted Pair
Lichtwellenleiter
Multimode Fiber
Monomode Fiber
Drahtlos
Funk
Mikrowellenfunk
Infrarot
Laser
7.4.2
Wie funktionieren Lichtwellenleiter?
Ein Lichtwellenleiter besteht aus einer sehr dünnen Glasfaser, die von einer Glasshülle umschlossen wird.
Das ganze wird dann noch durch eine Kunsstoffhülle geschützt. Am einen Ende der Leitung sitzt eine
Lichtquelle, zum Beispiel eine Laserdiode, am anderen Ende sitzt ein Detektor. Vereinbarungsgemäss
steht Licht an für 1 und Licht aus für 0. Aufgrund der Brechungs- und Beugungsgesetze verlässt
das Licht den Leiter nicht, sondern ist praktisch in ihm gefangen und kann wegen der minimalen
Dämpfung über sehr weite Entfernungen übertragen werden.
7.4.3
Welche Arten von Lichtwellenleitern gibt es?
siehe 7.4.1.
7.5
Schicht 2a
7.5.1
Welche Medienzugriffsverfahren kennen Sie?
siehe 7.5.7.
7.5.2
Erklären Sie CSMA-CD.
In der 1-persistenten Variante läuft CMSA/CD so ab:
– sendewillige Station überwacht den Kanal (Carrier Sense)
– ist der Kanal frei, wird gesendet
– ist der Kanal belegt, wird er weiter überwacht bis er frei ist, dann wird sofort übertragen
– während der Übertragung wird der Kanal weiter abgehört
– bei Erkennung einer Kollision wird die Übertragung abgebrochen und ein JAM-Signal gesendet
– danach wird entsprechend des Binary-Backoff-Algorithmus’ gewartet
– jetzt geht es von Vorne wieder los
7.5.3
Wie funktioniert ALOHA?
ALOHA ist ein Vielfachzugriffsverfahren ohne Reservierung und ohne Carrier Sense. Es gibt zwei
verschiedene Arten von ALOHA.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
83
Kapitel 7. Rechnernetze
pure ALOHA. Bei pure ALOHA kann jede Station senden, wann sie will, sie macht kein Carrier
Sensing. Während des Sendens hört die Station weiter mit und kann dadurch erkennen, ob ihre
Daten korrekt gesendet wurden oder nicht. Wenn es einen Fehler gab, sendet sie einfach nochmal.
Die maximale Ausnutzung der Bandbreite liegt bei 18%.
slotted ALOHA. Bei slotted ALOHA wird die Zeit in sog. Slots unterteilt. Um die Slots zu synchronisieren, kann z. B. eine Station als Taktgeber fungieren. Bei slotted ALOHA dürfen die Station
nicht zu jeder Senden, sondern immer nur zu Beginn eines Slots. Durch slotted ALOHA kann die
Leistung in etwa verdoppelt werden.
7.5.4
Was ist DQDB?
DQDB ist in der IEEE Norm 802.6 definiert und beschreibt ein MAN. DQDB wird in der 4. Auflage
des Tanenbaums nicht mal erwähnt, scheint also nicht mehr relevant zu sein.
7.5.5
Wie funktioniert FDDI?
Fiber Distributed Data Interface ist ein Lichtwellenleiter basiertes Token-Ring-LAN, das 100 Mbps über
Entfernungen von 200km unterstützt. FDDI wird in der 4. Auflage des Tanenbaums nur noch am Rande
erwähnt.
7.5.6
Wie funktioniert die Manchester-Codierung?
Codierungsverfahren, bei dem die binären Informationen durch Spannungswechsel innerhalb der Bitzeit
dargestellt werden. Dadurch können Sender und Empfänger wesentlich leichter synchronisiert werden,
denn der Übergang in der Mitte der Bitzeit gibt einen zuverlässigen Takt. Eine binäre 1 wird durch
ein High-Signal gefolgt von einem Low-Signal dargestellt, ein 0 genau umgekehrt. Die ManchesterCodierung ist self-clocking , d.h. es muss kein extra Taktsignal gesendet werden. Der Empfänger
kann den Takt selbst erkennen. Deshalb hat bei Ethernet jeder Frame eine 7 Byte lange, aus der Folge
10 bestehende, Präambel.
Nachteil der Manchester-Codierung ist, dass die doppelte Bandbreite
benötigt wird.
7.5.7
Geben Sie eine Einteilung der Vielfachzugriffsverfahren an.
Vielfachszugriffsverfahren
ohne Reservierung
ohne
Carrier Sense
pure
Aloha
7.5.8
slotted
Aloha
mit Reserverierung
mit
Carrier Sense
p-persistent
nonpersistent
statisch
TDM
dynamisch
FDM
Token
Wie funktioniert der Binary-Back-Off-Algorithm?
Nach i Kollision wird eine Zufallszahl zwischen 0 und 2i − 1 gewählt. Entsprechend dieser Zufallszahl
wird gewartet. Nach 10 Kollisionen wird die Wartezeit nicht mehr erhöht. Nach 16 Kollisionen meldet
der Controller einen Fehler.
7.5.9
Was ist der Konfliktparameter?
Eine Nachricht darf bei CSMA/CD nicht komplett in den Kanal passen, sonst kann eine Kollision
auftreten, ohne dass die sendende Station das bemerkt. Betrachten wir den Worst-Case.
84
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.5. Schicht 2a
Wir haben zwei Stationen A und B, die genau an den beiden Enden des Mediums liegen. Jetzt sendet
A einen Frame FA . Kurz bevor der Frame am anderen Ende des Kabels ist, sendet die dortige Station
einen Frame FB . B erkennt den Frame FA von A und sendet wegen der Kollision sofort ein JAM-Signal
J. Dieses muss jetzt aber wieder über das ganze Kabel bis zu A. Wichtig ist das A zu den Zeitpunkt,
in dem das JAM-Signal bei ihm eintrifft noch nicht mit dem Senden des Frames F A fertig ist, sonst
würde sie nichts von der Kollision mit bekommen.
Um das zu gewährleisten gibt man den Frames eine Mindestlänge, so dass eine sendende Station mindestens so lang mit senden beschäftigt ist, wie das Signal zum Ende des Leiters und das JAM-Signal
zurück benötigt. Die maximale Kabellänge muss natürlich auch spezifiziert sein.
Nehmen wir an die Signallaufzeit von einem Ende des Mediums zum anderen beträgt t Zeiteinheiten,
dann muss eine Station zum Senden eines Frames mindestens 2 · t Zeiteinheiten benötigen, damit nichts
schief geht. Der Konfliktparameter K beschreibt genau diesen Zusammenhang:
K=
2·t
∆t
Wobei ∆t die Nachrichtenübertragungszeit ist. Um das vorhergesagte zu formalisieren, fordern wir dass
K=
2·t
<1
∆t
immer gelten muss. Wenn wir für ∆t den Quotienten aus Framelänge l und Kanalübertragungsrate λ
einsetzen, können wir die minimale Framelänge lmin berechnen.
K
lmin
7.5.10
=
⇓
>
2·t
2tλ
=
<1
∆t
l
2tλ
Wie funktioniert Token Ring?
Token Ring verwendet ein dynamisches Vielfachzugriffsverfahren mit Reservierung. Ein Token kreist in
dem (physischen) Ring. Wenn eine Station senden will, muss sich den Token vom Ring nehmen. Nur
wer einen Token hat darf senden.
7.5.11
Vergleiche Sie CSMA/CD und Token Ring/Bus?
Da ein Token verloren oder kaputt gehen kann oder eine Station eine Token nicht mehr her geben kann,
ist das Tokenmanagement von Token Ring/Bus ist deutlich aufwendiger als CSMA/CD. Siehe dazu
auch 7.5.12.
7.5.12
Was passiert bei Token Ring, wenn eine Station ausfällt?
Ein wirkliches Problem ergibt sich beim Ring, wenn das Kabel reisst. Falls eine Station ausfällt (oder
abgeschaltet) wird entfällt auch die Verzögerung die sie normalerweise auf das Token hat, das Token
muss dann eventuell an anderer Stelle stärker verzögert werden. Ein anderes Problem ist, dass es bei
Token Ring immer eine Überwachungsstation gibt, die dafür u. a. dafür zuständig verloren gegangene
Tokens zu ersetzen. Fällt diese aus, muss eine andere einspringen, was oft zu Problemen führt.
7.5.13
Was ist der Vorteil von Switched Ethernet?
Die Kollisiondomänen sind kleiner, dadurch gibt es weniger Kollisionen. Die Sicherheit wird erhöht, da
nicht jede Station den ganzen Datenverkehr mit bekommt.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
85
Kapitel 7. Rechnernetze
7.6
Schicht 2b
7.6.1
Was ist Sliding Window ?
Sliding Window beschreibt ein Verfahren zur Flusskontrolle das flexibler als Stop-And-Wait ist. Die
Idee ist folgende. Bei Stop-And-Wait muss der Sender immer auf die Bestätigung für einen Frame
warten, bevor er den nächsten senden darf. Bei langen Signallaufzeiten wird dadurch sehr viel Kapazität
verschwendet. Besser wäre es, wenn der Sender mehrere Frames verschicken kann und dann nach und
nach die Bestätigungen bekommt. Grundvoraussetzung für Sliding Window ist, dass jeder Frame eine
eindeutige Sequenznummer hat. Damit können Duplikate unterschieden werden. Sowohl der Sender wie
auch der Empfänger haben ein Fenster von Sequenznummern, die bei beiden unterschiedliche Funktionen
erfüllen. Diese Fenster heissen entsprechen Sendefenster und Empfangsfenster. Beide Fenster sind
jeweils durch eine unter und obere Grenze begrenzt. Diese Grenzen sind Sequenznummern.
Die Sequenznummer im Sendefenster sind die Frames die verschickt wurden oder verschickt werden
dürfen, für die aber noch keine Bestätigung eingegangen ist. Wenn ein Paket von der Netzwerkschicht
kommt wird ein Frame mit der nächsten höchsten Sequenznummer erstellt und die obere Grenze des
Sendefensters wird um eins erhöht. Dadurch verwaltet das Sendefenster immer eine List von noch
nicht bestätigten Frames. Da theoretisch all diese Frames verloren gehen könnten, muss der Sender von
jedem eine Kopie speichern. Dafür braucht er Speicherplatz und daher ist Grösse des Fensters begrenzt.
Falls die Grösse des Fensters erschöpft ist und die Netzwerkschicht weiterhin versucht neue Pakte zu
verschicken, muss die Sicherungsschicht der Netzwerkschicht signalisieren, sich zu gedulden und keine
neuen Pakete mehr anzuliefern, bis wieder Platz im Sendefenster entstanden ist. Der Sender muss
ausserdem aufhören zu Senden, wenn ihm die Sequenznummern ausgehen. Wenn z. B. 3 Bits für die
Sequenznummer verwendet werden, kann er 8 Frames verschicken ohne eine Bestätigung zu bekommen,
dann muss er auf eine Bestätigung warten.
Das Empfangsfenster entspricht den Frames die der Empfänger bereits ist anzunehmen. Alle ankommenden Frames, die ausserhalb des Fensters liegen, werden sofort verworfen. Wenn ein Frame ankommt, dessen Sequenznummer der unteren Grenze des Empfangsfensters entspricht, wird dieser an
die Netzwerkschicht weitergegeben, eine Bestätigung verschickt und das ganze Empfangsfensters (ober
und untere Grenze) um eins nach oben geschoben (rotiert). In der Bestätigung, die an den Sender
geschickt wird, steht die Sequenznummer des letzten korrekt erhaltenen Frames, so weiss der Sender,
ob alles klar gegangen ist und kann das nächsten Frame verschicken. Falls der Empfänger einen Frame
empfängt, der nicht die aktuell erwartete Sequenznummer hat, kann er nach zwei Strategien vorgehen.
Die einfachere wird go back n genannt. Der Empfänger akzeptiert die Frames einfach nicht und sendet
keine Bestätigungen (dieses Verfahren ergibt sich automatisch, wenn die Grösse des Empfangsfensters 1
ist). Die aufwendigere Methode nennt sich selective repeat. Wenn der Empfänger einen Fehler entdeckt,
schickt er dem Sender eine negative Bestätigung (NAK) und sagt ihm genau, welcher Frame fehlt, der
Sender kann diesen dann nochmal schicken. Erst wenn der Empfänger eine vollständige Sequenz von
Frames hat, gibt er diese an die Netzwerkschicht weiter.
Wichtig ist, dass die Reihenfolge der Frames beim Senden zwar durcheinander kommen kann, aber der
Netzwerkschicht die Pakete immer in der richtigen Reihenfolge übergeben werden.
7.6.2
Welche Verfahren zur Flusssteuerung kennen Sie?
Zur Flusskontrolle gibt es feedback-basierte Mechanismen und rate-basierte Mechanismen, in der Sicherungsschicht werden aber nur feedback-basierte Mechanismen eingesetzt. Zwei Protokolle sind StopAnd-Wait und Sliding Window. Sliding Window wird in 7.6.1 beschrieben. Stop-And-Wait ist sehr
einfach. Der Sender sendet einen Frame, dann wartet er solange, bis er eine Bestätigung vom Empfänger
bekommen hat. Erst dann sendet er den nächsten Frame.
7.6.3
Wie teilt der Empfänger bei dem Sender Sliding Window mit, dass er mit dem Senden aufhören soll?
Wenn der Empfänger überfordert ist, sendet er keine Bestätigungen mehr. Dadurch muss der Sender
früher oder später aufhören zu Senden, da sein Sendefenster erschöpft ist.
Bei HDLC (7.6.7) kann der Empfänger einen Supervisory-Frame vom Typ Recieve Not Ready an
den Sender schicken.
86
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.6. Schicht 2b
Bei TCP schickt der Empfänger dem Sender immer die Grösse seines Empfangsfensters mit, wenn er
überfordert ist, schickt er eine 0.
7.6.4
Wie funktioniert CRC?
Die Grundidee von CRC ist, dass man eine Folge von n Bits als ein Polynom vom Grad n − 1 dessen
Koeffizienten nur 0 oder 1 sind, betrachten kann. Polynomielle Arithmetik wird modulo 2 durchgeführt,
daher entspricht Addition und Subtraktion einem einfach XOR. Das Prüfsummenverfahren läuft nun
wie folgt ab. Sender und Empfänger einigen sich auf eine Generatorpolynom G(x), wobei das höchste
und das niedrigste Bit 1 sein muss. Um einen Frame mit m Bits, die dem Polynom M (x) entspricht
zu verschlüsseln, muss der Frame länger sein als das Generatorpolynom. Nun hängt man an den
eigentlichen Frame eine Checksumme an, so dass das gechecksummte Frame durch G(x) teilbar ist.
Wenn der Empfänger eine Frame erhält versucht er ihn durch G(x) zu teilen. Gibt es einen Rest, liegt ein
Übertragungsfehler vor. Dadurch ergibt sich folgender Algorithmus zur Berechnung der Checksumme:
1. r sei der Grad von G(x). An den Frame werden auf der niederwertigen Seiten r 0-Bits angehängt.
Er hat jetzt m + r Bits und entspricht dem Polynom xr M (x).
2. Diese Polynom xr M (x) wird nun entsprechen der Modulo-2-Division durch G(x) geteilt.
3. Dabei ergibt sich ein Rest von r oder weniger Bits. Dieser wird nun von Bitstring der x r M (x)
entspricht entsprechend der Modulo-2-Subtraktion abgezogen. Das ist nun der gechecksummte
Frame, der T (x) genannt wird.
Es stellt sich die Frage, warum T (x) durch G(x) teilbar ist. Das ist eine fundamentale Eigenschaft der
Division, es gilt immer:
Divisor | Dividend − Rest
Zum Beispiel gilt für 9/4 mit Rest 1: 4 | 9 − 1. Die Güte der Checksumme ist bei CRC abhängig vom
Grad des Generatorpolynoms. Allgemein gilt mit einem Generatorpolynom vom Grad k findet man
alle Bit-Fehler der Länge ≤ k. Wenn man das Polynom geschickt wählt kann man ausserdem noch alle
Bitfehler die eine ungerade Anzahl an Bits betreffen finden. Das liegt daran, dass kein Polynom mit
einer ungeraden Anzahl an Termen das Polynom x2 + 1 als Faktor hat. Wenn x2 + 1 ein Faktor des
Generatorpolynoms ist, dann findet man die ungeradlängigen Bitfehler. Es gibt einige international
standardisierte Polynome. Ethernet verwendet das folgende Polynom vom Grad 3
x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1
Die Berechnung der CRC kann in Hardware sehr effizient gelöst werden.
7.6.5
Welche Fehler werden durch CRC erkannt?
siehe 7.6.4.
7.6.6
Wie sichert man Nachrichteninhalt?
Mit Checksummen, z. B. CRC (siehe 7.6.4).
7.6.7
Was ist HDLC?
High-Level Data Link Control ist ein älteres bitorientiertes Sicherungsprotokoll das vor allem in öffentlichen
Paketvermittlungsnetzen eingesetzt wird. Das Protokoll nutzt ein Flag und bit-stuffing um die Frames
voneinander zu trennen. Zur Flusskontrolle wird ein Sliding Window verfahren mit einer 3 Bit Sequenznummer verwendet. Es gibt drei verschiedene Arten von Frames: Information, Supervisory und
Unnumbered. Wobei Information-Frames für normale Datenübertragung, Supervisory-Frames für Signalisierung und die Unnumbered-Frames für verschieden Zwecke verwendet werden. Unnumbered-Frames
können für verbindungslose Kommunikation benutzt werden. Die Supervisory-Frames können verschiedene Typen haben. Wichtige Typen sind Recieve Ready für normale Bestätigung und Reject für
negative Bestätigung. Zusätzlich gibt es Recieve Not Ready um den Sender mitzuteilen, dass der
Empfänger nicht mehr mitkommt und Selective Reject um einen Fehler für einen bestimmten Frame
anzuzeigen.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
87
Kapitel 7. Rechnernetze
7.7
Schicht 3
7.7.1
Erklären Sie, was Schicht 3 macht.
siehe 7.2.1.
7.7.2
Was sind statische und adaptive Routing-Verfahren?
Bei statischen Routing-Verfahren werden die Wegewahlentscheidungen im Vorhinein ohne bestimmt.
Adaptive Routing-Verfahren passen die Entscheidungen mit Messungen an die aktuellen Gegebenheiten
an.
7.7.3
Ist auf Schicht 3 eine zuverlässige Übertragung möglich?
Schicht 3 kann sowohl verbindungsorientiert als auch verbindungslos sein. IP ist eine Beispiel für eine
verbindungslose Technik, ATM für eine verbindungsorientiert.
7.7.4
Wie funktioniert Routing im Internet?
In autonomen Subnetzen (AS) wird heute hauptsächlich OSPF eingesetzt. Zwischen den AS meisten
BGP.
7.7.5
Erklären Sie Shortest-Path-First-Routing.
Beim Shortest-Path-Routing werden die kürzesten Pfade im Netzwerk mit einem typischen Algorithmus wie Dijkstra bestimmt. Das Kantengewicht kann auf verschiedene Arten gewählt werden. Es kann
einfach immer 1 betragen, den zählt man nur die Hops oder man wählt andere Faktoren wie die physische Distanz, Übertragungszeit oder die durchschnittlichen Queueingzeiten. Auch eine Kombination
der Faktoren ist möglich. Die Routingentscheidungen werden dann entsprechend der kürzesten Wege
bestimmt.
7.7.6
Erklären Sie Distance-Vector-Routing.
Distance-Vector-Routing ist ein dynamischer Algorithmus, der wie folgt funktioniert. Jeder Router
verwaltet einen Vektor mit den besten bekannten Entfernungen zu jedem Ziel und der entsprechenden Leitung. Diese Tabelle werden immer wieder geupdatet in dem mit den Nachbarn Informationen
ausgetauscht werden. Für jeden Zielrouter enthält der Vektor einen Eintrag mit der zu wählenden Ausgangsleitung und einen Eintrag für die geschätzte Entfernung zum Ziel. Mögliche Metriken hier sind
Hops, Übertragungszeit oder Queueingzeiten. Jeder Router kennt die Entfernung zu seinen Nachbarn,
falls die Metrik nicht Hops ist, kann der Router die Entfernung anhand einer Analyse seiner Queue
oder durch Messung von Signallaufzeiten bestimmen. In einem bestimmten Zeitintervall verschickt jeder Router die von ihm geschätzten Zeiten an seine Nachbarn. Mit den neu erhaltenen Tabellen der
Nachbarn kann jeder Router entscheiden, ob es bessere Wege zu manchen Zielen gibt, als in seinem
Vektor gespeichert ist.
Distance-Vector-Routing hat ein grosses Problem, es findet zwar eine gute Konfiguration, aber sehr
langsam. Das Problem ist vor allem, dass sich gute Nachrichten sehr schnell, schlechte aber sehr langsam
verbreiten. Das ist als Count-to-Infinity-Problem bekannt. Der Kern des Problems liegt daran, dass
wenn X Y mitteilt, dass er irgendwohin einen Pfad hat, Y nicht weiss, ob er selber auf dem Pfad liegt
oder nicht.
7.7.7
Erklären Sie Link-State-Routing.
Link-State-Routing ist adaptiver Routing-Algorithmus bei dem Informationen über die Netztopologie
und alle Verzögerungszeiten gesammelt und an jeden Router verteilt wird. Dann können mit dem
Dijkstra-Algorithmus die kürzesten Pfade bestimmt werden. Jeder einzelne Router geht nach folgenden
Schritten vor:
88
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.7. Schicht 3
1. Nachbarn entdecken und deren Adressen merken.
Als erstes Sendet der Router über jede seiner Leitungen ein Hello-Paket. Als Antwort erhält er
vom Router auf der anderen Seite dessen Adresse. Diese Adressen müssen eindeutig sein.
2. Die Verbindungskosten zu jedem Nachbarn messen.
Jetzt sendet er an jeden Nachbarn ein Echo-Paket um die Verzögerung zu messen. Er kann dies
mehrmals durchführen und einen Durchschnittswert wählen. Ob hierbei die Auslastung der Leitung
mit in die Kalkulation aufgenommen wird, ist ein Diskussionspunkt.
3. Ein Paket zusammenstellen, dass die gerade gelernten Informationen enthält. Jetzt baut der Router
ein Paket mit den gewonnen Informationen zusammen. Diese Paket enthält die Adresse des Router,
eine Sequenznummer, ein Alter und eine Liste der Nachbarn. Für jeden Nachbarn enthält es die
gemessene Verzögerungszeit. Die Frage ist nur, wann die Pakete verschickt werden. Dies kann
entweder periodisch erfolgen oder wenn ein besonderes Ereignis, zum Beispiel ein nicht erreichbarer
Router, auftritt.
4. Dieses Paket an alle anderen Router schicken.
Das verschicken des Pakets ist er komplizierteste Teil, das sich Inkonsistenzen ergeben können, wenn
manchen Router schon die neuen Information erhalten haben und andere nicht. Grundsätzlich
basiert das Verfahren bei der Verteilung auf Flooding. Um das Flooding kontrollieren zu können,
versieht der Router jedes Paket, das er versendet mit einer neuen Sequenznummer. Jeder Router
speichert eine List von Paaren (Router, Sequenznummer), die er gesehen hat. Wenn ein neuen Paket
ankommt, prüft er ob dieses neu ist, wenn ja verschickt er es an alle Router ausser dem Quellrouter.
Wenn es ein Duplikat ist, verwirft er es. Wenn er ein Paket mit einer niedrigeren Sequenznummer
als die höchste, die der Router bisher gesehen hat, ankommt, lehnt er das Paket ab, weil es alt ist.
Es ergeben sich ein Paar Probleme, die aber in den Griff zu bekommen sind. Als erstes müssen die
Sequenznummern am besten 32-bitig sein, damit sie nicht überlaufen. Wenn ein Router ausfällt
und seine Sequenznummer vergisst, daher wieder bei 0 anfängt, werden seine Pakte nirgendwo mehr
angenommen. Falls eine Paket kaputt geht und z. B. statt der Sequenznummer 4 eine 65.540 enthält,
was auf einen 1-Bitfehler zurückzuführen ist, werden alle Pakete zwischen Sequenznummer 5 und
65.540 nicht mehr angenommen. Alle Probleme können mit dem Age-Feld der Pakete behoben
werden. Das Alter eines bereits empfangenen Paketes wird jede Sekunde um 1 herunter gezählt.
Paket mit Alter 0 sterben. Das Alter wird am Anfang so gesetzt, das normalerweise immer ein
neues Paket vom entsprechenden Router ankommt, bevor es stirbt. Ausserdem wird beim Flooding
am Anfang das Alter bei jedem Hop herunter gezählt, damit Paket nicht verloren gehen können.
5. Kürzeste Pfade zu allen Router berechnen.
Wenn ein Router die komplette Menge an Link-State-Paketen bekommen hat, kann er daraus die
Topologie des kompletten Netzes erschliessen und mit Hilfe von Dijkstra die kürzesten Pfade berechnen.
Der Algorithmus funktioniert sehr gut und wird zum Beispiel bei OSPF eingesetzt. Defekte Hardoder Software kann den Algorithmus aber empfindlich stören. Wenn z. B. ein Router behauptet eine
bestimmte Verbindung zu haben, wird der Graph auf dem die Berechnung basiert, inkorrekt.
7.7.8
Erklären Sie OSPF.
OSPF ist ein Internet Routing Protokoll für autonome Subnetze, es wird ein Link-State-RoutingAlgorithmus verwendet, siehe dazu 7.7.7.
7.7.9
Nennen Sie ein nicht-adaptives, isoliertes Routing-Verfahren.
Ich denke, hier ist Broadcasting gemeint.
7.7.10
Was ist RIP?
RIP ist ein älteres Internet Routing Protocol, es verwendet Distance-Vector-Routing, siehe dazu 7.7.6.
7.7.11
Unterschied zwischen IPv4 und IPv6
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
89
Kapitel 7. Rechnernetze
Die wichtigsten Unterschiede zwischen IPv4 und IPv6 sind
IPv6 benutzt 16 Byte Adresse, das entspricht ca. 3, 4 · 1038 Adressen. Das Adressproblem ist damit
behoben.
Die Unterstützung für Optionen wurde verbessert. Zum einen dadurch, dass das Optionsfeld im
IP-Header grösser ist, zum anderen werden die Information jetzt so gespeichert, das Router über
Informationen, die nicht für sie bestimmt sind, einfach hinweg springen können.
IPv6 hat verbesserte Unterstützung für Quality of Service.
IPv6 hat Unterstützung für diverse Sicherheitsmechanismen wie Authentifizierung.
7.7.12
Erzählen Sie etwas zum IP-Protokoll.
Das IP-Protokoll ist ein verbindungsloses Schicht 3 Protokoll. Zur Adressierung werden die bekannten
IP-Adressen verwendet. Jedes IP-Paket besteht aus einem Header- und einem Datenteil. IP Pakete
können bis 65.535 Bytes lang sein, sind aber in der Praxis meist 1500 Byte lang.
7.7.13
Wozu braucht man das TTL-Feld im IP-Header?
Das Time to Live-Feld im IP-Header wird bei jedem Hop runtergezählt, damit z. B. zyklisch geroutete
Paket nicht ewig Kreisen (bei TTL=0 stirbt das Paket).
7.7.14
Was ist Flooding?
Flooding ist ein sehr einfaches statisches Routingverfahren bei dem jedes ankommende Pakete über
alle Leitung aus der Quellleitung weitergeleitet wird. Damit Flooding nicht ausartet, muss es irgendwie
eingedämmt werden, entweder durch Hopcounter oder es werden Sequenznummern vergeben, so dass ein
Router ein bereits einmal gefloodetes Paket nicht nochmal floodet. Flooding ist meist nicht praktikabel
findet aber doch seine Anwendung. Zum einem ist wahnsinnig robust, selbst wenn fast alle Netzknoten
ausfallen und nichts mehr funktioniert, tut Flooding noch seinen Dienst. Ausserdem ist Flooding der
Prüfstein für alle anderen Routingalgorithmen, da Flooding dadurch, dass es alle Wege wählt, immer
den kürzesten Weg wählt.
7.7.15
Was ist hot potatoe?
Beim Hot-Potatoe-Routing können Pakete nicht gespeichert werden, sondern werden wie eine heisse
Kartoffel weitergegeben. Kommt z. B. in Backbone-Netzen vor wenn ein Carrier Daten von anderen
Carriern möglichst schnell wieder los werden will. Wird auch bei optischem Routing verwendet, wo
Lichtsignale nicht zwischengespeichert werden können.
7.7.16
Was ist Staukontrolle?
Im Gegensatz zur Flusskontrolle die dafür da ist, das ein Sender einen Empfänger, die beide an einer
Punkt zu Punkt Verbindung hängen, nicht mit Daten überflutet, wird beim Thema Staukontrolle das
komplette Netz betrachtet. Ein Stau existiert immer dann, wenn die Belastung des Netzes grösser ist
als seine Ressourcen. Im Falle eines Staus können entweder die Ressourcen erhöht werden, oder, wenn
das nicht geht, die Belastung gedrosselt werden. Generell unterscheidet man bei Staukontrolle zwischen
Open Loop- und Closed Loop-Methoden.
Open Loop Methoden. Open Loop Methoden versuchen das Problem durch gutes Design zu lösen,
das heisst durch gute Planung im Vorhinein, während des Betriebs wird nicht mehr eingegriffen.
Möglichkeiten den Stau im voraus zu vermeiden bestehen an mehreren Stellen.
Data Link Layer. In der Sicherungsschicht sollte die Flusskontrolle unnötige Frames verhindern,
also z. B. selective repeat und piggybacking einsetzen.
Network Layer. In der Netzwerkschicht ist vor allem die Entscheidung zwischen verbindungsorientierten und verbindungslosen Diensten ausschlaggebend, da viele Staukontrolle-Algorithmen
nur mit Verbindungen arbeiten. Ausserdem ist Wahl eines Routing-Algorithmus’, der die Last
gut verteilt, wichtig.
90
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.8. Schicht 4
Transport Layer. Auch in der Transportschicht muss die Flusskontrolle unnötig versandte Daten
vermeiden.
Closed Loop Methoden. Closed Loop Methoden reagieren auf den aktuellen Zustand des Netzes,
dieser Ansatz besteht immer aus drei Teilen:
1. Überwachung des Netzes. Wo und wann treten Verstopfungen auf?
2. Verteilung der Stauinformation an relevante Stellen.
3. Behebung des Problems
Die folgenden Verfahren lassen sich nur bei verbindungsorientierter Kommunikation einsetzen.
Wenn ein Stau entdeckt wurde, werden keine neuen Verbindungen mehr aufgebaut (Admission
Control ).
Verbindungen können vorsichtig um heikle Stelle herumgeführt werden.
Es können bereits beim Verbindungsaufbau Verträge abgeschlossen werden. So fordert ein
Kunde zum Beispiel eine gewisse Bandbreite, die Verbindung wird nur aufgebaut, wenn diese
Bandbreite auch zur Verfügung steht.
Im verbindungslosen Netzen muss anders vorgegangen werden. Ein Router kann die Auslastung
seiner Ports messen, dieser Auslastung kann er eine Zahl zwischen 0 und 1 zuordnen. Jetzt wird eine
Auslastungsobergrenze festgelegt. Wann immer ein Router ein Paket auf einem Port rausschicken
soll, dessen Auslastung die Obergrenze übersteigt, muss er irgendwie reagieren. Dafür gibt es
mehrere Möglichkeiten:
Warning Bit. Der Router kann in ausgehenden Pakete ein Warning Bit auf 1 setzen, die Zielstation setzt dann ihrerseits ein Warning Bit in dem zu sendenden Bestätigunspaket, dass wieder
zum Sender zurück läuft. Dieser drosselt daraufhin das Senden. Das dauert zwar relativ lang, hat
aber den Vorteil, dass nicht in der schon bestehenden Stausituation noch extra Pakete versandt
werden müssen.
Choke Packets. Wenn der Router eine Überlastung feststellt sendet er ein Choke Packet an den
Sender, der daraufhin drosselt.
Hop-by-Hop Choke Packets. Es kann u. U. recht lange dauern, bis das Choke Packet beim Sender
angekommen ist. Mit einem Hop-by-Hop Choke Packet kann der Router den Router vor ihm
bitten, den Datenverkehr durch Pufferung zu drosseln. Dieser bittet wieder seinen Vorgänger
usw.
Load Shedding. Wenn die vorangegangen Methoden alle nichts Helfen, kann der Router zu
brutaleren Methoden greifen, er verwirft einfach einen Teil der Pakete. Wenn der Router eine
Ahnung von der Art der Daten hat (z. B. Multimedia) kann er erst einmal möglichst unwichtige
Pakete verwerfen.
Random Early Detection. Bei einigen Transportprotokollen (z. B. TCP) reagiert der Sender
bei verloren Pakete mit einer Drosselung der Sendegeschwindigkeit. Das liegt daran, dass in
kabelbasierten Netzen, für die z. B. TCP hauptsächlich entworfen wurde, fehlende Bestätigung
meist auf Pufferüberläufe zurückzuführen sind. Wenn dem so ist, kann der Router, wenn er
merkt, dass ein Stau kurz bevor steht manche Pakete der Quelle die die hohe Auslastung erzeugt,
einfach verwerfen. Die Quelle reagiert dann mit der Drosselung der Sendeleistung. Das verfahren
heisst early weil der Router das tut, bevor alles verstopft ist und random weil er aus der Queue
in der er die Überlastung feststellt, zufällig ein Paket wählt und dieses verwirft. Dadurch wählt
er den zu drosselnden Sender zufällig.
7.8
Schicht 4
7.8.1
Was ist das Transportsystem?
Unter dem versteht man die Schichten 1-4.
7.8.2
Ist Schicht 4 immer verbindungsorientiert?
Nein. UDP z. B. ist nicht verbindungsorientiert.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
91
Kapitel 7. Rechnernetze
7.8.3
Erzählen sie etwas zu TCP.
TCP ist das verbindungsorientiert Schicht 4 Protokoll der Internetprotkollfamilie. Eine TCP-Verbindung
wird immer von einem Socket zu einem anderen aufgebaut. Ein Socket ist eine IP-Adresse plus Port.
Eine TCP-Verbindung ist Byte basiert, nicht Nachrichten basiert. Der Verbindungsaufbau läuft bei
TCP über den Three-Way Handshake (7.8.4). Zur Flusskontrolle verwendet TCP ein Sliding Window Verfahren. Bei dem von TCP verwendeten Verfahren teilt der Empfängen dem Sender immer die
Grösse seines Empfangsfensters mit. Wenn er es auf 0 setzt, kann er damit den Sender drosseln. Die
ursprüngliche Version unterstützt kein Selective Repeat sondern nur go back n. Interessant ist, dass
die TCP-Checksumme ausser dem Header und den Daten noch einen Pseudoheader mit ein berechnet.
Dieser Pseudoheader enthält Ziel- und Quelladresse. Diese Verwendung von IP-Adressen auf Schicht
4 verletzt die Protkollhierarchie. Bei der Trennung der Verbindung werden Timer benutzt um das
Two Army-Problem zu umgehen. Die Staukontrollemechanismen von TCP beruhen auf der Annahme
das Pakete hauptsächlich wegen Pufferüberläufen und nicht wegen schlechter Leitungsqualität verloren
gehen. Dies führt bei unsicheren Funkverbindungen zu Problemen. Zur Staukontrolle verwendet verwaltet der Sender neben dem Sendefenster zusätzlich ein Congestion Window. Dieses Fenster kann an
die aktuelle Belastung des Netzes angepasst werden.
7.8.4
Was ist der Three-Way Handshake?
Beim Aufbau einer TCP-Verbindung muss – bevor eine Verbindung zustande kommt – zunächst eine
Verständigung zwischen Sender und Empfänger stattfinden. Dazu verwendet TCP die Methode des
Three-Way Handshake. Das heißt es müssen zunächst drei TCP-Pakete gesendet werden bevor die Verbindung aufgebaut ist. Erst mit einem erfolgreichen letzten und drittem Segment erfolgt der Handschlag
und die Verbindung besteht.
Angenommen man hat Host A, der eine Verbindung mit Host B, aufnehmen möchte, passiert folgendes:
1. Im ersten Paket von A nach B:
ACK-Flag
SYN-Flag
Sequenznummernfeld
Acknowledgementfeld
=
=
=
=
0
1
initiale Sequenznummer
nicht benutzt
2. Möchte B die Verbindung aufnehmen schickt er ein Paket nach A
ACK-Flag
SYN-Flag
Sequenznummernfeld
Acknowledgementfeld
=
=
=
=
1
1
initiale Sequenznummer
Sequenznummer von A inkrementiert
3. Handschlag von A nach B
ACK-Flag
SYN-Flag
Sequenznummernfeld
Acknowledgementfeld
=
=
=
=
1
0
initiale Sequenznummer inkrementiert
Sequenznummer von B inkrementiert
Nach diesen drei Schritten ist die Verbindung aufgebaut. Möchte man den Aufbau einer TCP-Verbindung
unterbinden muss man das erste Paket heraus filtern. So wird der weitere Aufbau einer Verbindung
unmöglich. Das ACK-Flag spielt hier die entscheidende Rolle, da dieses Flag nur im ersten Paket nicht
gesetzt ist. So werden bestehende TCP-Verbindungen nicht beeinträchtigt, da hier in allen Paketen das
ACK-Flag gesetzt ist.
Die Abbildung zeigt den Three-Way Handshake in seiner üblichen Darstellung. A, S sind das ACK bzw. SYN -Flag, SEQ und ACK sind das Sequenznummernfeld und Acknowledgementfeld.
92
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
7.8. Schicht 4
Host 1
Host 2
ASS
0 1 EQ ACK
x
Time
CK
EQ A
A S S y x+1
11
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
ASS
1 0 x EQ ACK
+1 y
+1
93
Kapitel 8
Rechnernetze II
8.1
Allgemeines
8.2
Hochleistungsnetze
8.2.1
Gibt es bei ATM MAC-Adressen?
ATM verwendet sein eigenes Adressformat. Genauer gesagt gibt es drei verschiedene Adressformate,
die alle 20 Byte lang sind. Die Abbildung zeigt das DCC-Format.
1
AFI
2
3
4
5
6
7
8
DCC
9
10
HO-DSP
11
12
13
14
15
16
17
ESI
18
19
20
SEL
Im ersten Byte, dem Authority Format Identifier (AFI) wird das Adressformat angegeben, der Wert
39 steht für das DCC-Format. In den folgenden zwei Bytes steht der Data Country Code (DCC). Er
bestimmt das Land, 276F steht für die BRD. Byte 4 bis 13 werden vom High Order Domain Specific
Part (HO-DSP) belegt. Hier sind die Routing Domain und der Area Identifier abgelegt. Den Rest der
20 Byte teilen sich der End System Identifier (ESI) und das Selector Field (SEL). Wobei dem ESI die
Rolle einer MAC-Adresse bei einem Ethernet-Gerät zukommt. Das SEL spielt eine ähnliche Rolle wie
Ports bei IP. Wenn auf einer Maschine mehrere Dienste (z. B. BUS und LECS) laufen, so werden sie
durch das SEL unterschieden.
8.2.2
Wie funktioniert bei ATM die Vermittlung?
Ein Vermittler liest die VPI/VCI-Information der ankommende Zelle aus dem Header und routet die
Zelle anhand von Tabellen. In internen Vermittler (Vermittler, die keine Verbindung zum einem Host
haben) kann das Routing nur in Abhängigkeit von der VPI-Information gemacht werden. Das hat
mehrere Vorteile. Der Vermittler muss verhältnismässig kleine Tabellen speichern. Dass Routing ist
schneller und Routen lassen sich sehr schnell für viele VCs umleiten.
8.2.3
Geben Sie einen kurzen Überblick über ATM.
ATM (Asynchronous Transfer Mode) ist eine verbindungsorientierte Netzwerktechnologie, die Datenraten bis 622 MBit/s bietet. Die Verbindungen heissen Virtual Circuits (VC) und können entweder
permanent oder switched sein. Mehrere VCs können zu einem Virtual Path (VP) zusammengefasst
werden. Das bietet die Möglichkeit, eine ganze Sammlung von VCs zu routen. Ausserdem können
QoS-Parameter einem ganzen Pfad zugeordnet werden. ATM setzt statt Pakete Zellen von 53 Byte
Länge, die einen 5 Byte Header haben ein. Welche Vorteile der Einsatz von Zellen hat, beschreibt 8.2.6.
ATM-Verbindungen bieten keine garantierte Zellzustellung, aber alle Zellen werden in der richtigen
Reihenfolge zugestellt.
Das ATM-Modell lässt sich im Gegensatz zum OSI-Schichtenmodell besser dreidimensional darstellen.
Die Benutzerebene betrifft Datentransport, Flusssteuerung, Fehlerkorrektur und andere Benutzerfunktionen. Die Steuerebene beschäftigt sich mit dem Verbindungsmanagement. Ebenen- und Schichtenmanagement sind für Ressourcenmanagement und Schicht übergreifende Koordination zuständig.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
95
Kapitel 8. Rechnernetze II
Ebenenmanagement
Schichtenmanagement
Steuerebene
Obere Schichten
CS
SAR
Benutzerebene
Obere Schichten
ATM-Anpassungsschicht
ATM-Schicht
TC
PMD
Physische Schicht
Die Physische Schicht und die Anpassungsschicht bestehen aus zwei Teilschichten, wobei jeweils die
untere die Arbeit tut und die oberen für die Schnittstelle nach oben zuständig ist.
Die ATM-Anpassungsschicht (ATM Adaption Layer, AAL) hat die Aufgabe die Datenströme der höheren
Schichten auf 48-Byte Lange Zellen zu segmentieren, bzw. aus den ATM-Zellen wieder die ursprünglichen
Datenpakete zu erstellen (Reassembly). Es gibt verschiedene Typen der ALL-Schichte, derzeit sind AAL
1–5 spezifiziert. Je nach Anwendung (z. B. Clip) wird eine andere Schicht gewählt.
Die Hauptaufgabe der ATM-Sicht besteht darin, die von der AAL-Schicht empfangenen Daten an ihren
Bestimmungsort zu transportieren. Die Informationseinheit der ATM-Schicht sind die 53-Byte Zellen.
Die ATM-Schicht ist vollkommen unabhängig von der unter ihr liegenden physischen Schicht.
Die physische Schicht ist für die Generierung der ATM-Zellen, Checksummen-Berechnung und das
tatsächliche Versenden zuständig.
Für eine genauer Beschreibung der Funktion der Schichten siehe auch 8.2.4.
8.2.4
Vergleichen Sie das ATM-Schichtenmodell mit dem ISO–OSI–Schichtenmodell.
Physische und AAL-Schicht (AAL = ATM Adaption Layer) sind jeweils zweigeteilt. Wobei die eigentliche Arbeit in der unteren Schicht stattfindet und die Konvergenzschicht darüber die Schnittstelle
nach oben bietet. Die Tabelle gibt einen Überblick über die Schichten des ATM-Modells und zeigt
auch die korrespondierenden Schichten im OSI-Modell. Der Versuch die Schichten von ATM in das
OSI-Schichtenmodell einzuordnen ist nicht unproblematisch.
OSI
ATM
Teilschicht
Funktionalität
3/4
AAL
CS (Convergence
Sublayer)
SAR (Segmentation and
Reassembly Sublayer)
2/3
ATM
2
Physisch
Bereitstellung der Standardschnittstelle
(Konvergenz)
Segmentierung und erneute Zusammensetzung
Flusssteuerung
Erzeugung/Extraktion des Zellheaders
Management des virtuellen Pfades
Multiplexen/Demultiplexen der Zellen
Entkoppelung der Zellrate
Erzeugung der Header-Prüfsummen
Erzeugung der Zellen
Ein-/Auspacken der Zellen
Erzeugung von Rahmen
Bitzeitgabe
Physischer Netzzugriff
1
8.2.5
96
TC (Transmission
Convergence Sublayer)
PM (Physical Medium
Dependent Sublayer)
i Wie sieht die Sicherungsschicht bei ATM aus?
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
8.3. Dienstgüte
Die Sicherungsschicht des OSI-Modells entspricht einer Mischung der Transmission Convergence Layer
und der ATM-Schicht. Siehe 8.2.4.
8.2.6
Bei ATM-Zellen hat man einen relativen hohen Protokoll-Overhead, warum macht man das?
Der wichtigste Grund ist, dass sich durch die kleine Zellengrösse die Zellen schneller (eventuell
parallel) verarbeiten lassen. Zellrouting wird in Hardware realisiert.
Da Pakete (im Verhältnis zu Zellen) sehr gross werden können, müssen neu ankommende Pakete,
die übertragen werden sollen, im Mittel sicherlich länger warten.
Bei Übertragungsfehlern muss immer ein ganzes Paket neu übertragen werden. Wenn nur an einer
Stelle eines Pakets ein Fehler aufgetreten ist, müssen u. U. 64k übertragen werden. Das ist ungefähr
1200 mal so viel wie bei einer ATM-Zelle.
Durch die feste Zellengrösse die lassen sich genauer Werte über z. B. die Belegungsdauer genauer
bestimmen und vorhersagen.
8.2.7
Würden Sie ATM lokal einsetzen?
Im Vergleich zu Ethernet kann ATM hauptsächlich noch durch QoS punkten. Wenn QoS tatsächlich
die zentrale Anforderung an das Netz ist (z. B. Video-Übertragung), dann könnte ATM eine Überlegung
wert sein. Zu Berücksichtigen ist, dass ATM sehr teuer und sehr aufwendig zu konfigurieren ist. Ausserdem lässt es sich sehr schlecht in eine IP-Umgebung einbauen, wenn man nicht auf QoS verzichten
will, oder man muss eine noch aufwendigere manuelle Konfiguration vor nehmen. Mit derzeitigen
LAN-Technologien bekommt man eventuell für das selbe Geld ein so dermassen überdimensioniertes
Gigabit-Ethernet, dass sich QoS von alleine erledigt.
8.3
Dienstgüte
8.3.1
Was ist QoS?
Dienstgüte (Quality of Service) bezeichnet quantifizierbare Eigenschaften eines Dienstes. Die einzelnen
Eigenschaften werden als Dienstgüteparameter oder Merkmale bezeichnet. Die wichtigsten Merkmalsklassen sind:
Bandbreite (Bandwidth). gemessen in Bit/s.
Verzögerung (Delay). gemessen in ms.
Jitter. Jitter ist die Standardabweichung der Verzögerung.
Zuverlässigkeit (Reliability). Hier interessiert sowohl die Zerstörung als auch der Verlust von Daten.
Unterschiedliche Anwendungen haben unterschiedliche Anforderungen an die Merkmalsklassen, die Tabelle gibt einen Überblick.
Anwendung
eMail
Dateitransfer
WWW
Remote Login
Audio niedrig
Video niedrig
Telephonie niedrig
Videokonferenz niedrig
8.3.2
Zuverlässigkeit
hoch
hoch
hoch
hoch
niedrig
niedrig
niedrig
niedrig
Verzögerung
niedrig
niedrig
mittel
mittel
niedrig
niedrig
hoch
hoch
Jitter
niedrig
niedrig
niedrig
mittel
hoch
hoch
hoch
hoch
Bandbreite
niedrig
mittel
mittel
niedrig
mittel
hoch
niedrig
hoch
Welche Strategien gibt es für QoS?
Overprovisioning. Man stellt einfach so viele Ressourcen zur Verfügung, dass alle QoS-Bedürfnis von
selbst erfüllt werden. Das Problem bei dieser Lösung ist der Kostenfaktor. Das normale Telefonnetz
ist ein Beispiel für diese Lösung.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
97
Kapitel 8. Rechnernetze II
Buffering. Ein Datenstrom kann gepuffert werden. Diese beeinflusst Zuverlässigkeit und Bandbreite
nicht. Es erhöht die Verzögerung bietet aber die Möglichkeit Jitter zu vermindern.
Traffic Shaping. Traffic Shaping kann als rate basierte Flusskontrolle betrachtet werden. Bei Verfahren wie Sliding Window wird Menge an Daten die verschickt wird kontrolliert. Beim Traffic
Shaping kontrolliert man die Datenübertragungsrate. Die Idee beim Traffic Shaping ist, dass der
Sender beim Verbindungsaufbau einen Vertrag eingeht, der ihm eine gewisse Datenrate zusichert,
wenn er eine gewissen Senderate nicht überschreitet. Zur Realisierung von Traffic Shaping werden Leaky Bucket- oder Token-Bucket-Algorithmen eingesetzt. Wichtig ist, das beim Buffering auf
Empfängerseite gepuffert wird, beim Traffic Shaping auf Senderseite.
Resource Reservation. Das Abschliessen eines Traffic Contracts erlaubt es den an der Verbindungen
teilnehmenden Router entsprechend Ressourcen zu reservieren. Ressourcen sind Bandbreite, Puffer
und Rechenzeit.
Admission Control. Wenn ein Router erkennt, dass es die im Vertrag geforderten Anforderungen
nicht erfüllen kann, darf er die Verbindung nicht annehmen.
8.3.3
Wie garantiert man eine niedrige Auslastung?
Um eine niedrige Auslastung garantieren zu können, dürfen die Anforderung in den angenommenen
Traffic Contracts die Ressourcen nicht überschreiten.
8.3.4
Was ist Jitter?
Jitter ist die Standardabweichung der Verzögerung, also die durchschnittliche Abweichung von der
durchschnittlichen Verzögerung. Video und speziell Audio ist sehr anfällig für Audio. Da das menschliche Ohr Schwankungen sofort raus hört.
8.3.5
Was ist ein isochroner Dienst?
Bei isochronen Diensten sollten Sender und Empfänger möglichst gleich laufen (also kein Jitter).
8.3.6
Welche Dienstklassen bietet ATM?
Constant Bit Rate (CBR). Durch die konstante Bitrate eignet sich die CBR-Klasse um eine Kupferoder Glasfaserleitung zu emulieren. Damit kann z.B. ein Sprachkanal realisiert werden, der sich
wie ein herkömmlicher ISDN B-Kanal verhält. Ausserdem kann die CBR-Klasse zur EchtzeitÜbertragung unkomprimierter Video/Audio-Daten verwendet werden.
Realtime Variable Bit Rate (RT-VBR). Bei den meisten Komprimierungsverfahren für Audio und
Video (z.B. MPEG) entsteht eine Datenstrom mit unterschiedlichen Bitraten. Um Echzeitanwendungen zu ermöglichen wird in dieser Klasse garantiert, dass kein Jitter auftritt. Der gelegentliche
Bit- oder Zellverlust ist im Gegensatz zum Jitter zu verschmerzen.
Non Realtime Variable Bit Rate (nRT-VBR). Diese Klasse eignet sich ebenfalls für Anwendungen
mit variierender Bitrate, gibt aber keine Jitter-Garantie.
Unspecified Bit Rate (UBR). Die UBR-Klasse mach keinerlei Garantien über die Bitrate und warnt
auch nicht vor Überlastungen. Dieses Verfahren ähnelt dem von IP und eignet sich daher auch gut
für die Übertragung von IP-Paketen.
Available Bit Rate (ABR). Die ABR-Klasse bietet die Möglichkeit eine Verbindung zwischen A und
B zu beantragen, die immer mindestens 5 MBit/s leistet, aber nach Möglichkeit des Netzes auch
mehr zur Verfügung stellt. So kann man z.B. angeben, dass Spitzen von 10 MBit/s auftreten können.
Die 5 MBit/s sind dann garantiert und die 10 MBit/s werden nach Möglichkeit zur Verfügung
gestellt. Diese Klasse würde sich z.B. für Web-Surfen eignen.
8.3.7
Welche Möglichkeiten gibt es QoS über IP zu realisieren?
Für QoS in IP-Netzwerken gibt es zwei verschieden Ansätze
98
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
8.3. Dienstgüte
Integrated Services. Hier ist die Idee ähnlich wie bei ATM eine Verbindung mit zugesicherten Eigenschaften aufzubauen. Dazu müssen auf jedem einzelnen Router die Ressourcen reserviert werden.
Das dabei verwendete Protokoll heisst Resource Reservation Setup Protocol (RSVP). Das Problem
ist genau, dass jeder Router dieses Protokoll unterstützen muss. Ausserdem ist die Skalierbarkeit
eher begrenzt, weil für jede Verbindung ein RVSP-Tunnel aufgebaut werden muss.
Differentiated Services. Bei diesem Ansatz werden keine Verbindungen aufgebaut, sondern die
Pakete in verschiedene Prioritätsklassen eingeteilt und dann entsprechend ihrer Priorität geroutet.
Dies ist insofern einfach zu realisieren, da auch der IPv4 Header ein Type Of Service Feld enthält.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
99
Literaturverzeichnis
[Duden Informatik, 1993]
Duden Informatik. 2. Aufl. Dudenverlag, 1993
[Hennesy & Patterson, 2003]
Hennesy, John L.; Patterson, David A. Computer Architecture: A Quantitative. Approach. 3. Aufl. Morgan Kaufman, 2003
[Jessen, 2001]
Jessen E. Skript zur Vorlesung Rechnerarchitektur WS 00/01.
[Rechenberg & Pomberger, 1999] Rechenberg, Peter; Pomberger, Gustav (hrsg.) Informatik-Handbuch. 2. Aufl.
Hanser, 1999
[Tanenbaum, 1997]
Tanenbaum, Andrew S. Computernetzwerke. 3. Aufl. Prentice Hall, 1997
[Tanenbaum, 2001]
Tanenbaum, Andrew S. Modern Operating Systems. 2. Aufl. Prentice Hall,
2001
[Tanenbaum, 2003]
Tanenbaum, Andrew S. Computer Networks. 4. Aufl. Prentice Hall, 2003
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
101
Teil III
Theoretische Informatik
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
103
Kapitel 9
Effiziente Algorithmen und
Datenstrukturen
9.1
Allgemeines
9.1.1
Was ist dynamisches Programmieren?
Wie Divide&Conquer wird beim dynamischen Programmieren ein Problem in Subproblem aufgeteilt,
diese gelöst und die Gesamtlösung aus den Teillösungen zusammengesetzt. Dynamisches Programmieren
verwendet man, wenn die Subproblem (im Gegensatz zu Divide&Conquer) nicht unabhängig sind.
Zwischenergebnisse werden in Tabellen gespeichert. Dynamisches Programmieren kommt meist bei
Optimierungsproblemen zum Einsatz.
9.1.2
Ein Beispiel für dynamische Programmierung?
Knapsack, Floyd-Warshall, CYK, LCS
9.1.3
Wie können Graphen repräsentiert werden?
Mit Adjazenzenlisten oder Adjazenzenmatrizen.
9.1.4
i Was versteht man unter amortisierter Kostenrechnung?
Mit der amortisierten Kostenrechnung gibt man die durchschnittlichen Kosten von Operationen in
Folgen an. Angegeben wird der Worst-Case aller Folgen.
Eine Möglichkeit die amortisierten Kosten zu bestimmen ist die Potentialmethode, die wie folgt funktioniert. Man startet mit einer Datenstruktur D0 , auf der n Operationen ausgeführt werden. Für jedes
i = 1, 2, . . . , n gibt ci die tatsächlichen Kosten der i-ten Operation an. Di ist die Datenstruktur, die
durch Anwendung der i-ten Operation auf die Datenstruktur Di−1 entsteht. Eine Potentialfunktion Φ
ordnet jeder Datenstruktur Di ein reelle Zahl Φ(Di ) zu. Diese Zahl ist das Potential der Datenstruktur
Di . Die amortisierten Kosten ĉi der i-ten Operation unter Berücksichtigung der Potentialfunktion Φ
ist definiert durch
ĉi = ci + Φ(Di ) − Φ(Di−1 ).
Die amortisierten Kosten einer Operation sind also die tatsächlichen Kosten plus die Potentialzunahme.
Wenn die Potentialzunahme bei Operation i positiv ist, wird sozusagen überbezahlt, das Potential der
Datenstruktur erhöht sich. Ist sie negativ, wird angespartes Potential aufgebraucht.
Für die amortisierten Kosten von n Operationen gilt somit (der zweite Schritt ergibt sich wegen der
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
105
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
Teleskopsumme)
n
X
ĉi
=
i=1
=
n
X
i=1
n
X
i=1
(ci + Φ(Di ) − Φ(Di−1 ))
ci + Φ(Dn ) − Φ(D0 )
Wichtig ist, dass gelten muss Φ(Dn ) − Φ(D0 ) ≥ 0, sonst sind die amortisierten Kosten keine obere
Schranke der tatsächlichen Kosten. Da man in vielen Fällen die Anzahl n der Operationen zu Beginn
nicht weiss, muss man dafür sorgen, dass für alle i Φ(Di ) ≥ Φ(D0 ) gilt. Oft ist es praktisch, Φ(D0 ) = 0
zu setzen und für jedes i > 0 zu zeigen, dass Φ(Di ) ≥ 0 gilt.
9.1.5
Was ist Divide&Conquer?
Bei Divide&Conquer wird ein Problem in Subprobleme zerlegt, diese werden (rekursiv) gelöst und die
Gesamtlösung aus den Teillösungen zusammengesetzt.
9.1.6
Welche Aussagen können Sie über die Laufzeit von Divide&Conquer-Algorithmen machen?
Wenn man die Rekursionsgleichung für einen Divide&Conquer-Algorithmus kennt, kann in vielen Fällen
mit Hilfe des Master Theorems die Laufzeit bestimmt werden.
Master Theorem:
Seien α ≥ 1 und β ≥ 1 zwei Konstanten und sei f (n) eine nicht negative Funktion und sei T (n) definiert
durch die Rekursionsgleichung
n
+ f (n)
T (n) = αT
β
l m
j k
wobei nβ sowohl als nβ als auch als nβ gelesen werden kann, dann ist

Θ nlogβ α , wenn f (n) = O nlogβ α−
für ein konstantes > 0,



 Θ nlogβ α log n , wenn f (n) = Θ nlogβ α ,
logβ α+
T (n) =
Θ (f (n)) ,
wenn
für ein konstantes > 0 und

f(n) = Ω n



αf nβ ≤ cf (n) für ein konstantes 0 < c < 1.
Man erkennt das die Laufzeit von Divide&Conquer-Verfahren hauptsächlich von der Funktion f , die
für das Zusammensetzen der Gesamtlösung aus den Teillösungen zuständig ist, abhängt.
9.1.7
Erklären Sie den Unterschied zwischen Worst-Case-, Average-Case- und amortisierten Kosten.
Worst-Case-Kosten. Die Worst-Case-Kosten geben eine obere Schranke für die Laufzeit an, gelten
also unabhängig von der Art der Eingabedaten.
Average-Case-Kosten. Die Average-Case-Kosten geben die Kosten für einen durchschnittlichen Ablauf eines Algorithmus an. Dies macht aber noch eine Aussage über das Worst-CaseVerhalten. Ein Beispiel ist Quicksort, dass Average-Case-Kosten von O(n log n) hat, im schlechtesten Fall aber quadratische Kosten hat.
Amortisierte Kosten. Bei bestimmten Datenstrukturen wie Fibonacci-Heaps macht es keinen Sinn
alle Operationen getrennt zu betrachten, da die Operationen dort sehr unterschiedlich viel Arbeit
verrichten. Deshalb werden dort Folgen von Operationen auf eine Datenmenge betrachtet. Angegeben werden dann die durchschnittlichen Kosten pro Operation für den Worst-Case aller Folgen.
9.1.8
Was sind Graphen?
Ein Graph ist ein Tupel (V, E), wobei V eine endliche Menge von Knoten ist und E ⊆
von Kanten ist.
106
V
2
eine Menge
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.2. Mathematische Grundlagen
9.1.9
Was ist die transitive Hülle?
Die transitive Hülle eines gerichteten Graphen G = (V, E) ist der Graph G∗ = (V, E ∗ ) wobei
E ∗ = {(i, j) | es gibt einen Pfad von Knoten j nach i in G}
ist.
9.1.10
Was ist das uniforme und was das logarithmische Kostenmaß?
Beim uniformen Kostenmaß wird die Länge (in Bits) der einzelnen Operatoren nicht beachtet, beim
logarithmischen Kostenmaß schon. Das logarithmische Kostenmaßmuss verwendet werden, wenn die
Operator sehr gross sind (im Vergleich zur normalen Registergrösse).
Beispiel: Der Algorithmus,
der testet ob eine Zahl n eine Primzahl
√ ist hat im uniformen Kostenmaß
√
die Komplexität O( n), da er einfach für alle Zahlen {2, 3, . . . , n} testet ob sie die Zahl n teilen.
Nun das logarithmische Kostenmaß. Wenn die Zahl n binär√kodiert wird, beträgt die Eingabelänge
l = log2 n. Als Laufzeit erhält man für den Algorithmus O( 2l ) was aber leider O(2l/2 ) entspricht.
Dieser Algorithmus hat also exponentielle Laufzeit und ist daher für grosse n unbrauchbar.
9.1.11
Was ist das allgemeine Prinzip das im CYK-Algorithmus verwendet wird?
Dynamische Programmierung.
9.1.12
Welche algorithmische Prinzipien kennen Sie (mit Beispielen)?
Greedy: Kruskal, Prim
Divide&Conquer: Mergesort, Quicksort
Dynamische Programmierung: Knapsack, Floyd-Warshall, CYK, LCS
9.2
Mathematische Grundlagen
9.2.1
i Sie haben in der Vorlesung Rekursionsgleichungen kennen gelernt. Erzählen Sie etwas dazu.
Da die Laufzeit von vielen Algorithmen mit einer Rekursionsgleichung beschrieben werden kann, interessiert man sich für die geschlossene Form solcher Rekursionsgleichungen. Zur Bestimmung dieser Form
existieren verschiedene Verfahren.
Formeln. Für einfache Rekursionsgleichung, d. h. homogene und inhomogene Rekursionsgleichung
ersten Grades sowie homogene Rekursionsgleichung zweiten Grades existieren Lösungsformeln. Siehe dazu [DS-Faq, 2001].
Substitutionsmethode. Die Idee bei der Substitutionsmethode ist, eine obere Grenze für die Rekursionsgleichung zu raten und diese durch Nachrechnen zu beweisen. Dies wird z. B. beim der
Laufzeitanalyse von BFPRT gemacht (9.4.14).
Iterationsmethode. Die Idee bei der Iterationsmethode ist, die Rekursion immer wieder zu expandieren und somit eine Form zu erreichen, die nur von n und den Startbedingungen abhängt. Der
Vorteil ist, dass man keine obere Grenze erraten muss, dafür erfordert sie einiges an Rechenarbeit. Manchmal kann man ohne die Iterationsmethode zu Ende zu führen das Ergebnis erraten und
dann die Substitutionsmethode anwenden.
Master-Theorem. Die Laufzeit von Divide&Conquer-Algorithmen lässt sich oft mit dem MasterTheorem bestimmen, siehe dazu 9.1.6.
Erzeugendenfunktionen. Ein sehr mächtiges (aber auch recht komplexes) mittel zum Lösen von Rekursionsgleichungen sind Erzeugendenfunktionen, siehe dazu [DS-Faq, 2001] und [Graham et. al., 1989].
9.2.2
i Wie kann man eine Rekursionsgleichung mit Hilfe einer Erzeugendenfunktion lösen?
Das ist in [DS-Faq, 2001] und [Graham et. al., 1989] ausführlich beschrieben.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
107
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
9.3
Datenstrukturen
Hinweis: Wenn nicht anders angegeben gilt im Folgenden n = |V | und m = |E|.
9.3.1
Was sind Fibonacci-Heaps und wieso heissen sie so?
Der Fibonacci-Heap ist eine Heap-Implementierung bei der alle Operationen bis auf Extract-Min
in O(1) ablaufen, Extract-Min benötigt O(log n). Die Grundidee der Fibonacci-Heaps ist, jegliche
Neuordnung des Heaps solange wie möglich hinauszuzögern. Nur bei Extract-Min wird der Heap
neu geordnet. Genau wie der Binomial-Heap besteht der Fibonacci-Heap aus mehreren Bäumen, die an
den Wurzel verbunden sind. Ausserdem gibt es einen Zeiger min[H] der auf das kleinste Element der
Wurzelliste und somit auf das kleinste Element überhaupt zeigt.
Insert (O(1)): Es wird ein neuer Baum mit einem einzigen Knoten erzeugt, dieser wird an die
Wurzelliste angehängt. Fall nötig wird min[H] umgesetzt.
Minimum (O(1)): Der Zeiger min[H] zeigt immer auf das kleinste Element.
Merge (O(1)): Die Wurzellisten der beiden Heaps H1 und H2 werden konkateniert. der Zeiger
min[H] wird auf min(min[H1 ], min[H2 ]) gesetzt.
Extract-Min (O(log n)): Bei dieser Operation wird die Neuordnung des Heaps durchgeführt und
zwar so, dass danach alle Wurzel der Wurzelliste unterschiedlichen Grad haben (der Grad gibt die
Anzahl der Söhne eines Knotens an). Es lässt sich zeigen, dass die amortisierten Kosten für das
Löschen des Minimums O(D(n)) betragen, wobei D(n) der maximale Grad eines Knotens einem
Heap mit n Knoten ist. Es gilt folgendes Lemma (size(x) bezeichnet die Anzahl der Knoten im
Unterbaum von x, x mitgezählt):
Lemma Für jeden Knoten x vom Grad k eines Fibonacci-Heaps gilt size(x) ≥ Fk+2 (daher der
Name Fibonacci-Heaps).
Mit diesem Lemma lässt sich nun Zeigen, dass D(n) = O(log n): Sei x einen Knoten mit Grad k
in einem n-Knoten Fibonacci-Heap. Laut Lemma gilt n ≥
√ size(x) ≥ Fk+2 . Weiterhin gilt, dass
Fk+2 ≥ φk , wobei φ der goldene Schnitt ist, φ = (1 + 5)/2. Somit gilt n ≥ size(x) ≥ φk .
Logarithmieren ergibt k ≤ logφ n. Also ist D(n) = O(log n).
Trotz der guten Laufzeiten werden Fibonacci-Heaps wegen der aufwendigen Implementierung in der
Praxis nicht sehr häufig eingesetzt.
9.3.2
Was ist ein Binary Heap?
Ein Binary Heap ist ein Binärbaum in dem für jeden Knoten gilt, dass sein Schlüssel grösser ist als die
Schlüssel aller Kinder.
1
16
2
3
14
10
1
8
2
4
5
6
7
8
7
9
3
9
4
2
3
4
5
6
7
8
9
10
16 14 10 8 7 9 3 2 4 1
10
1
Wie die Abbildung zeigt, werden Binary Heaps eigentlich immer als Arrays implementiert. Damit kann
sehr einfach auf den Vater sowie die rechten und linken Kinder zugegriffen werden:
Parent(i)
Left(i)
Right(i)
108
: bi/2c
: 2i
:
2i + 1
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
Mit Heaps kann sowohl der Heapsort Algorithmus als auch eine Priority Queue realisiert werden. Laufzeiten:
Insert
Extract-Max
Build-Heap
Heapify
Heapsort
9.3.3
O(log n)
O(log n)
O(n)
O(log n)
O(n log n)
stellt Heap-Bedingung wieder her
Was ist ein Binomial-Baum
Der Binomial-Baum Bk ist ein geordneter Baum, der rekursiv definiert ist.
der B0 hat nur einen einzigen Knoten.
der Bk besteht aus den beiden Binomial-Bäumen Bk−1 die wie folgt miteinander verbunden sind:
die Wurzel des einen Baumes ist das linkeste Kind der Wurzel des anderen Baumes
Der Baum Bk hat folgenden Eigenschaften:
1. es gibt 2k Knoten
2. die Höhe des Baumes ist k
3. auf der Tiefe i gibt es ki Knoten, daher der Name
4. die Wurzel hat Grad k, das ist der höchste vorkommende Grad im Baum
9.3.4
Was sind Binomial-Heaps und wieso heissen sie so?
Ein Binomial-Heap H ist eine Menge von Binomial-Bäumen die folgenden Bedingungen erfüllt.
1. jeder Binomial-Baum in H erfüllt die Heap-Bedingung so dass für jeden Knoten gilt, dass sein
Schlüssel mindestens so gross wie der seines Vater ist
2. jeder Bi kommt nur einmal in H vor
Diese Binomial-Bäume werden an den Wurzel durch eine Liste verbunden. Die zweite Bedingung besagt,
dass der Binomial-Heap H mit n Knoten höchstens blog nc + 1 viele Binomial-Bäume und damit auch
höchstens blog nc + 1 Wurzel in der Kette hat. Damit dauert die Suche nach dem kleinsten Element
O(log n).
Laufzeiten:
Make-Heap
Insert
Minimum
Extract-Min
Union
Decrease-Key
Delete
9.3.5
O(1)
O(log n)
O(log n)
O(log n)
O(log n)
O(log n)
O(log n)
Was sind Suchbäume?
Suchbäume sind Datenstrukturen, die folgende Operationen unterstützen:
Search
Minimum
Maximum
Predecessor
Successor
Insert
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
109
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
Delete
Suchbäume können für Dictionaries und Priority Queues eingesetzt werden.
9.3.6
Was sind Rot-Schwarz-Bäume?
Rot-Schwarz-Bäume sind externe Binärbäume mit roten und schwarzen Kanten, sodass gilt
1. Alle Blätter hängen an schwarzen Kanten.
2. Alle Blätter haben die gleiche Schwarztiefe.
3. Kein Pfad von der Wurzel zu einem Blatt enthält aufeinander folgende rote Kanten.
Die Schwarztiefe eine Knotens ist die Anzahl der schwarzen Kanten auf dem Pfad von der Wurzel
zum Knoten. Ein Rot-Schwarz-Baum hat die Tiefe O(log n), das führt zu den folgende Laufzeiten der
Dictionary-Operationen.
Search. Die Suche funktioniert wie immer in einem Suchbaum. Laufzeit ist O(log n).
Insert. Wie bei den (a, b)-Bäumen wird zuerst Search durchgeführt um das Blatt w zu finden,
wo der einzufügende Schlüssel noch nicht hängt. Das Blatt w wird dann durch einen Knoten w 0 mit
Kinder w und v ersetzt. Wobei v den neuen Schlüssel hat. Wenn danach zwei aufeinander folgende
rote Kanten an w 0 liegen, wird durch Rotation oder Doppelrotation wieder die Ordnung hergestellt.
Laufzeit ist O(log n).
Delete. Beim Löschen eines Schlüssels muss der Vater des Blattes durch den Bruder des Blattes ersetzt werden um die Binärbaumstruktur aufrecht zu halten. Danach steht u. U. eine Reorganisation
des ganzen Baumes verändert werden. Trotzdem ist die Laufzeit O(log n).
Rot-Schwarz-Bäume können zur Implementierung von (2, 4)-Bäumen dienen.
9.3.7
Was ist eine Priority Queue?
Priority Queue ist eine Datenstruktur, die folgende Operationen unterstützt:
Insert
Minimum
Extract-Min
(Decrease-Key)
9.3.8
Wo werden PQs verwendet?
Bei den Algorithmen von Prim und Dijkstra. Kruskal kann auch mit PQs implementiert werden.
9.3.9
i Wie kann man PQs implementieren?
Es gibt verschiedene Möglichkeiten zur Implementierung von PQs, die sich in den Laufzeiten und des
Aufwands unterscheiden.
Binary-Heaps
Binomial-Heaps
Fibonacci-Heaps
1-Level und 2-Level Buckets
Radix Heaps
9.3.10
Was sind Union-Find-Strukturen?
Eine Union-Find-Struktur erlaubt es Mengenoperationen effizient zu implementieren, sie stellt folgende
Operationen zur Verfügung.
110
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
Make-Set
Union
Find-Set
Die beste bekannte Implementierung von Union-Find-Strukturen funktioniert mit Bäumen, wobei die
Wurzel jeweils eines Baumes jeweils den Repräsentanten darstellt. Wenn noch die Heuristiken Union
by Rank und Path Compression angewandt werden, kann für m Operation auf n Element die Laufzeit
(mα(m, n)) erreichen. Wobei α die inverse Ackermannfunktion ist.
9.3.11
Erklären Sie die Union-Operation.
Wenn die Union-Find-Struktur als Wald implementiert ist, wird die Wurzel des kleineren Teilbaums an
die Wurzel des grösseren Teilbaums gehängt. Man nennt dieses Vorgehen Union by Rank und verwaltet
den Rang in einem Array rank [].
9.3.12
Was ist Pfadkompression?
Bei Find-Set werden alle Knoten direkt an die Wurzel gehängt, dadurch laufen folgende Find-SetOperationen schneller ab.
9.3.13
Welche Komplexität hat die Find -Operation bei Union-Find-Strukturen mit Path-Compression?
Wenn bereits vorher einmal nach einem Element der Menge gesucht wurde, ist die Komplexität O(1),
da alle Knoten direkt an der Wurzel hängen. Im schlimmsten Fall kann sie O(n) wobei n die Anzahl
der Knoten in diesem Teilbaum ist.
9.3.14
Was bedeutet log∗ n?
Dazu muss zuerst die Funktion log(i) n definiert werden.

wenn i = 0
 n
(i−1)
(i)
log(log
n) wenn i > 0 und log(i−1) n > 0
log n =

undefiniert
wenn i > 0 und log(i−1) n ≤ 0 oder log(i−1) n undefiniert
log∗ n ist dann wie folgt definiert.
log∗ n = min{i ≥ 0 | log(i) n ≤ 1}
Damit ist log∗ n genau die Umkehrfunktion zur wiederholten Potenzierung.
9.3.15
Was ist eine Rotation in einem Suchbaum?
Durch eine Rotation in einem Suchbaum kann ein Knoten um ein Niveau angehoben oder abgesenkt werden ohne das die Suchbaumeigenschaft verletzt wird. Der Begriff Rotation ist eigentlich irreführend.
Falls man sich wirklich eine Rotation vorstellen will, liegt das Rotationszentrum anschaulich eher auf
der Kante als am Knoten. Sonst würde ja nur der eine Knoten verändert. Die Abbildung zeigt Linksund Rechtsrotation.
RIGHT-ROTATE(y)
y
α
9.3.16
α
γ
x
β
x
LEFT-ROTATE(x)
y
β
γ
i Was sind Splay-Trees?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
111
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
Splay-Trees stellen eine selbst-organisierende Datenstruktur dar. Es handelt sich um binäre Suchbäume,
die aber im Gegensatz zu balancierten Bäumen keinen weiteren Bedingung unterliegen. Beim Zugriff
auf ein Element x wird eine Variante der Move-To-Root-Heuristik angewandt, die das Element an die
Wurzel des Baumes verschiebt und den Baum verbreitert. Die Länge aller Suchpfade zu Elementen
auf dem Suchpfad von x halbiert sich in etwa. Die Operation Splay(t, x) führt die Reorganisation für
Baum t und Element x durch. Die Wörterbuch-Operationen laufen wie folgt ab:
Search: Zuerst wird Splay(t, x) durchgeführt. Ist x enthalten steht es danach an der Wurzel,
ansonsten ist es nicht enthalten.
Insert: Um Element x in Baum t einzufügen, wird zuerst Splay(t, x) durchgeführt. Dadurch
können sich drei Fälle ergeben:
1. x steht an der Wurzel. In diesem Fall gibt es nichts zu tun, da das Element bereits vorhanden
ist.
2. x steht nicht an der Wurzel und x ist nicht kleiner als alle Elemente in t. In diesem Fall macht
man x zur Wurzel und hängt die Teilbäume der alten Wurzel entsprechend um.
3. x steht nicht an der Wurzel und x ist kleiner als alle Elemente in t. Auch in diesem Fall macht
man x zur Wurzel, allerdings ist danach der linke Unterbaum von x leer.
Delete: Um Element x aus t zu löschen wird zuerst Splay(t, x) durchgeführt. Falls x danach
nicht an der Wurzel steht, ist nichts zu tun, da x nicht im Baum enthalten ist. Andernfalls steht
x an der Wurzel und hatte den linken Unterbaum tl und den rechten Unterbaum tr . Jetzt wird x
gelöscht, danach führt man Splay(tl , ∞) aus, wobei ∞ eine Element ist, dass grösser ist als alle
Elemente in tl . Dadurch erhält man einem Baum t0l , der den grössten Schlüssel y von tl an der
Wurzel und eine leeren rechten Teilbaum hat. Diesen Teilbaum ersetzt man jetzt durch t r und hat
wieder eine gültigen Baum.
Mit einer amortisierten Kostenanalyse kann man Zeigen, dass m Splay-Tree-Operation auf n Elementen
O(m log n) Zeit brauchen, daher ergeben sich im Durchschnitt Kosten von O(log n) pro Operation.
9.3.17
Wie funktioniert die Splay-Operation?
Die Aufgabe der Splay(t, x)-Operation ist es, dass Element x an die Wurzel des Baumes zu verschieben
und den Baum breiter zu machen. Im Folgenden sei v der Knoten bei dem das Element gefunden wurde.
Falls x nicht gefunden wird, sei v der Vater des Blattes bei dem die Suche erfolglos endet. Der Vater
von v heisst p[v], der Grossvater von v ist g[v] = p[p[v]]. Die Splay(t, x)-Operation läuft nun in zwei
Schritten ab:
1. Zuerst wird der Knoten v gesucht.
2. Jetzt werden die Operationen Zig, Zig-Zig und Zig-Zag durchgeführt bis sie nicht mehr ausgeführt
werden können, weil v Wurzel des Baumes ist.
Die Operationen funktionieren so:
Zig: Diese Operation wird durchgeführt falls p[v] die Wurzel des Baumes ist. Es wird eine Rotation
nach links oder rechts durchgeführt, so dass v neue Wurzel des Baumes wird.
v
p[v]
γ
v
α
β
RR(p[v])
α
p[v]
β
γ
Zig-Zig: Diese Operation wird durchgeführt falls v einen Vater p[v] und einen Grossvater g[v]
hat und sowohl v als auch p[v] rechte (linke) Söhne ihres jeweiligen Vaters sind. Es werden zwei
aufeinander folgende Rotationen in die gleiche Richtung durchgeführt. Zuerst bei g[v] und dann
bei p[v], dadurch wird v um zwei Niveaus angehoben.
112
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
v
g[v]
p[v]
δ
p[v]
RR(g[v])
γ
v
α
RR(p[v])
v
α
p[v]
g[v]
β
α
β
βγ
δ
g[v]
γ
δ
Zig-Zag: Diese Operation wird durchgeführt falls v einen Vater p[v] und einen Grossvater g[v] hat
und einer der beiden Knoten v und p[v] linker und der andere rechter Sohn seines jeweiligen Vater
ist (oder umgekehrt). Jetzt werden zwei Rotationen in gegengesetzter Richtung durchgeführt. Die
erste bei p[v], die zweite bei g[v], dadurch wird v um zwei Niveaus angehoben.
g[v]
g[v]
v
α
p[v]
v
δ
RR(p[v])
α
LR(g[v])
v
g[v]
β
γ
β
p[v]
p[v]
γ
α
βγ
δ
δ
Der einzige Unterschied zur normalen Move-to-Root-Heuristik liegt in der Operation Zig-Zig. Hier
wird nicht wie bei Move-To-Root streng von unten nach oben vorgegangen, die Rotation wird zuerst
für den Grossvater und dann für den Vater durchgeführt.
9.3.18
i Was ist Hashing?
Hashing ist eine Methode mit der man die Wörterbuchoperation Insert, Delete und Search in
einigen Fällen mit der durchschnittlichen Laufzeit O(1) realisieren kann. Es wird eine Hashfunktion
definiert, die jedem Element k des Universums U einen Slot h(k) zuweist. Im folgenden gilt folgendes:
U ist das Universum, N = |U |
K ⊂ U ist die Schlüsselmenge, n = |K|
Array T [0 . . . m − 1] ist die Hashtabelle
Hashfunktion h : U → [0 . . . m − 1]
ki sind Schlüssel
h(ki ) sind Slots
9.3.19
Welche Probleme gibt es beim Hashing und wie werden die gelöst?
Probleme die beim Hashing auftreten können sind Kollisionen. Es kann passieren, das zwei (oder mehrere) Elemente k1 und k2 auf den selben Slot h(k) gehasht werden. Zur Behandlung solcher Kollisionen
gibt es mehrere Methoden:
1. Chaining
Alle Elementen die auf den selben Slot h(k) gehasht werden, werden in eine verkettete Liste gehängt,
deren Kopf in h(k) liegt. Beim Chaining ergeben sich folgende Laufzeiten:
Insert: O(1)
Delete: O(1) wenn die Listen doppelt verkettet sind, wenn nicht entspricht sie der von Search
Search: die Worst-Case-Laufzeit ist O(n), wenn alle Elemente im selben Slot landen. Wenn
man annimmt, dass die Hasfunktion die Element auf alle Slots mit gleicher Wahrscheinlichkeit verteilt ist die Average-Case-Laufzeit von Search O(1 + α), wobei α der load factor, das
Verhältnis der Elemente in der Tabelle zur Anzahl der Slots, ist. Dies gilt für erfolgreiche und
erfolglose Suche. Wenn die Anzahl der Slots proportional zur Anzahl der Elemente ist, führt
das zur Laufzeit O(1).
2. Open addressing
Beim Hashing mit offener Adressierung werden alle Element in der Tabelle selbst abgelegt. Wird
beim Insert oder Search des Schlüssels k ein Element 6= k im Slot h(k) gefunden, so wird auf
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
113
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
deterministische Weise eine alternative Adresse berechnet. Für jeden Schlüssel wird also eine Sondierungsfolge festgelegt. Das heisst die Hashfunktion bekommt einen zweiten Eingabeparameter
(die probe number ) der beim Insert inkrementiert wird, bis ein freier Slot gefunden wurde. Bei
Search wird ebenfalls inkrementiert bis der Schlüssel gefunden wurde oder ein leerer Slot entdeckt
wurde, dann endet die Suche erfolglos. Ein Problem ergibt sich beim Delete. Wenn man den
Schlüssel einfach löschen würde, zerbräche man die Sondierungsreihenfolge und könnte die dahinter liegenden Elemente nie mehr finden. Deshalb löscht man nicht, sonder markiert den Slot als
gelöscht . Dadurch sind die Laufzeiten aber nicht mehr von α abhängig. Aus diesem Grund
wird normalerweise Chaining verwendet, wenn auch gelöscht werden soll.
Für das Sondieren gibt es mehrere Vorgehensweisen. Generell gelten im folgenden diese Definitionen. h(k) ist ursprüngliche Hashfunktion, s(i, k) ist eine Sondierungsfunktion, die die Probe number
und einen Schlüssel nimmt und h(i, k) = (h(k) − s(i, k)) mod m. Man startet dann immer mit
h(k) und versucht, falls diese belegt ist, als nächstes h(1, k) = h(k) − s(1, k).
a) Linear Probing
Beim linearen Sondieren ist die Sondierungsfunktion wie folgt definiert:
s(i, k) = j
⇒
h(i, k) = (h(k) − j)
mod m
D. h. man probiert zuerst T [h(k)], dann T [h(k)−1], dann T [h(k)−2], usw. Lineares sondieren ist
sehr einfach zu implementieren hat aber das Problem des Primary Clustering. Um die Elemente
herum, die Kollisionen verursachen, bilden sich Häufungen. Für die durchschnittliche Anzahl
der Sondierungsschritte gilt:
  1 1+ 1
erfolgreich
2 1−α
E [# probes] =
1
1

erfolglos
2 1 + (1−α)2
b) Quadratic Probing
Beim quadratischen Sondieren ist die Sondierungsfunktion wie folgt definiert:
s(i, k) = (−1)j
2
j
2
D. h. man probiert T [h(k)], T [h(k) + 1], T [h(k) − 1], T [h(k) + 4], T [h(k) − 4], . . . Man muss hier
aufpassen, dass das auch tatsächlich eine Permutation über alle Slots ergibt. Es lässt sich zeigen,
dass dies für bestimmte prime m so ist. Das Clustering tritt hier viel weniger stark auf und
heisst Secondary Clustering. Für die durchschnittliche Anzahl der Sondierungsschritte gilt:

 1 + ln 1
erfolgreich
− α2
1−α E [# probes] =
1
1

erfolglos
1−α − α + ln 1−α
c) Double Hashing
Beim doppelten Hashing ist die Sondierungsfunktion wie folgt definiert:
s(i, k) = jh0 (k)
wobei h0 eine zweite Hashfunktion ist. Damit h(i, k) = (h(k) − s(i, k)) mod m eine Permutation
aller Hashadressen ergibt, muss h0 (k) für alle Schlüssel relativ prim zu m sein. Das kann man z. B.
erreichen indem man als m eine Zweierpotenz wählt und h0 so definiert, dass sie nur ungerade
Zahlen erzeugt.
Für die durchschnittliche Anzahl der Sondierungsschritte gilt:
E [# probes] =
9.3.20
114
1
1
α m 1−α
1
1−α
erfolgreich
erfolglos
i Was ist universelles Hashing?
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
Beim normalen Hashing kann es immer passieren, dass die Hashfunktion alle Schlüssel einer bestimmten
Eingabe in den selben Slot hasht und damit Worst-Case-Laufzeit produziert. Dies kann vermieden
werden, in dem die Hashfunktion zufällig aus einer Menge von Hashfunktionen gewählt wird. Sei H eine
solche Menge von Hashfunktionen. Die Menge h heisst universell wenn für jedes Paar unterschiedlicher
Schlüssel x, y ∈ U , die Anzahl der Hashfunktionen für die h(x) = h(y) gilt, genau |H|/m ist. Das
bedeutet, wenn man eine Hashfunktion h zufällig aus H auswählt ist die Wahrscheinlichkeit einer
Kollision zwischen zwei Schlüsseln x, y gleich 1/m. Dies entspricht genau der Wahrscheinlichkeit eine
Kollision zu erzeugen, wenn man die beiden Slots vollkommen zufällig bestimmen würde, also den
Annahmen des uniformen Hashings.
9.3.21
i Was ist perfektes Hashing?
Das folgende gilt nur für das statische Dictionary-Problem, wobei nur Search-Operation zugelassen
ist.
Eine Hashfunktion ist perfekt, wenn Sie alle Schlüssel auf unterschiedliche Slots abbildet.
Eine minimale perfekt Hashfunktion braucht nur den Platz m = |K| = n.
Für m ≥ 3n kann man in Zeit O(nN ) eine perfekte Hashfunktion für K ⊂ U finden, die in O(1)
auszuwerten ist (durch ein Programm der Grösse O(n log N ) Bits).
9.3.22
Welche Bäume setzt man in einer Datenbank ein?
B-Bäume.
9.3.23
9.3.24
Geben Sie eine grobe Klassifizierung von Datenstrukturen an.
Klasse
Operationen
Implementierung
Dictionary
Priority Queue
Mergeable Heaps
Concatenable Queues
Search, Insert, Delete
Minimum, Insert, Extract-Min, (Search)
Minimum, Insert, Delete, Merge
Minimum, Insert, Delete, Merge
Hashtabelle, balancierte Bäume
Heaps
2-3-Bäume, Binomial-Wälder
2-3-Bäume
Was sind (a, b)-Bäume?
(a, b)-Bäume sind Suchbäume mit den folgenden Eigenschaften.
Alle Blätter haben die gleiche Tiefe.
Die Schlüssel sind nur in den Blättern gespeichert (externer Suchbaum).
Für alle Knoten v ausser der Wurzel gilt: a ≤ #Kinder ≤ b.
Für die Wurzel gilt: 2 ≤ #Kinder ≤ b.
Es gilt b ≥ 2a − 1
Für alle inneren Knoten v gilt: Hat v l Kindern, so sind in v l − 1 Werte k1 . . . kl−1 gespeichert und
es gilt:
ki−1 < key(w) ≤ ki für alle Knoten w im i-ten Unterbaum von v, wobei k0 = −∞, kl = +∞
Die Wörterbuchoperationen funktionieren wie folgt.
Search (k). Der Algorithmus zum finden eines Elementes startet an der Wurzel und läuft entsprechend der Informationen, die in den Knoten gespeichert sind, nach unten bis zu einem Blatt. Dort
findet er entweder den gesuchten Schlüssel oder nicht.
Search(k)
1 v ← Wurzel
2 while (v ist kein Blatt) {
3
i ← min{1 ≤ j ≤ #Kinder(v) | k ≤ kj }
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
115
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
4
v ← i-tes Kind von v
5 }
6 if (k = key(v)) return True
7 else return False
Die Laufzeit ist O(Höhe(T )).
Insert (k). Beim Insert wird zuerst einmal wie beim Search ein Blatt gesucht, da an dessen
Vater der neue Schlüssel angehängt werden muss. Jetzt muss überprüft werden, ob der Knoten
dadurch nicht zu viele Kinder erhält. Wenn ja, muss er und eventuell seine Vorfahren aufgetrennt
werden. Im folgenden Algorithmus steht p(v) für den Vater von v.
Insert(k)
01 bestimme Blatt v wie in Search
02 w ← p(v)
03 füge k als zusätzliches Blatt von w ein
04 while (#Kinder(w) > b) {
05
if (w 6= Wurzel) y ← p(w)
06
else y ← neue Wurzel mit einzigem Kind w
07
zerteile w in zwei Knoten
w
1 und w2 ,
09
wobei w1 die b+1
kleinsten und
2
grössten
Kinder von w erhält.
10
w2 die b+1
2
11
füge den b+1
-ten
Schlüssel
von
w zu y
2
12
und zwar zwischen die Zeiger auf w1 und w2
13
w ← y //rekursiv weiter machen mit dem Vater
14 }
Die Abbildung zeigt einen 2, 3-Baum in der Schlüssel 22 eingefügt werden soll. Der Baum 0 ist
der Ausgangsbaum. Wenn nun 22 eingefügt wird, ergibt sich Baum 1 in dem das Blatt, an das
22 angehängt wurde, die Bedingung a ≤ #Kinder ≤ b verletzt. Deshalb wird dieser Knoten
aufgespalten (2). Dadurch hat die Wurzel ein Kind zu viel und es wird eine neue Wurzel eingefügt
(3). Der Knoten unter der Wurzel wird nun aufgespalten und alles ist in Ordnung.
0
1
4,13
1
1
7
4
7
17,21
13
17
21
4,13
1
24
1
2
7
4
7
1
7
4
7
13
21
17
1
22
21
22
24
22
24
1
7
4
7
17
13
17
22
21
22
24
13
4
21
1
116
17
4,13,21
17
4
1
13
3
4,13,21
1
17,21,22
7
4
7
17
13
17
22
21
22
24
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
Die Laufzeit ist O(Höhe(T )).
Delete (k). Zuerst wird der Schlüssel gesucht, wenn er nicht gefunden wird, wird abgebrochen.
Wenn er gefunden wurde, wird das Blatt entfernt, das kann dazu führen, dass dem Vater zu wenige
Kinder übrig bleiben.
01
02
03
04
05
06
07
08
09
10
11
bestimme Blatt v wie in Search
if (key(v) 6= k) return //Schlüssel nicht gefunden
w ← p(v)
entferne v von w
while ((#Kinder(w) < a) ∧ (w 6= Wurzel)) {
y ← linker oder rechter Nachbar von w
if (#Kinder(y) = a) verschmelze w und y
else adoptiere rechtestes bzw. linkestes Kind von y
w ← p(w) //rekursiv weiter machen mit dem Vater
}
if ((w =Wurzel) ∧ (Wurzel hat nur ein Kind)) lösche Wurzel
Die Abbildung zeigt einen 2, 3-Baum aus dem das Blatt mit dem Schlüssel 7 gelöscht wird. Der
Baum 0 ist der Ausgangsbaum. In Baum 1 wurde das Blatt bereits entfernt, dadurch hat der
Knoten 7 ein Kind zu wenig. Jetzt gibt es zwei Möglichkeiten den Knoten y zu wählen. Wird
der linke Nachbar gewählt, kommt man zu dem Fall, dass dieser genau a Kinder hat, dann wird
verschmolzen (2a). Wird der rechte Nachbarn gewählt, gilt dies nicht, deshalb adoptiert man das
linkeste Kind (2b).
0
1
4,13
1
1
7
4
7
2a
17,21
13
17
21
4
1
24
1
4
17
21
24
17,21
13
17
21
24
4,17
1
17,21
13
13
2b
4,13
1,4
1
4,13
1
13
4
13
21
17
21
24
Die Laufzeit ist O(Höhe(T )).
Die Laufzeiten der Wörterbuchfunktionen sind von der Höhe des Baumes abhängig. Um die Höhe
eines (a − b)-Baumes in Abhängigkeit von n zu bestimmen, muss man sich erstmal überlegen wie viele
Schlüssel der Baum der Höhe h speichert. Dieser Wert wird maximal, wenn jeder Knoten genau b
Kinder hat. Dann speichert der Baum bh Schlüssel. Minimal wird er, wenn die Wurzel zwei Kinder und
alle anderen Knoten a Kinder haben, dann speichert er 2ah−1 Schlüssel. Also gilt:
2ah−1 ≤ n ≤ bh
Das nun nach h aufgelöst ergibt
n
2
Da die Wörterbuchoperationen alle von der Höhe des Baumes abhängen gilt also für alle die Laufzeit
O(log n). Die Wahl der Parameter hängt von dem Speicherort der Daten ab. Wenn die Daten im
Hauptspeicher liegen, sollte man a klein, also z. B. 2 oder 3 wählen. Liegen die Daten auf der Festplatte,
wählt man a gross, z. B. a = 100.
logb n ≤ h ≤ 1 + loga
9.3.25
Was sind AVL-Bäume?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
117
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
AVL-Bäume sind balancierte Binäre Suchbäume bei denen für jeden Knoten v gelten muss, dass die
Höhe seines linken Unterbaums von der des rechten höchstens um 1 unterscheidet. Für die Laufzeiten
der einzelnen Operation gilt:
Search
Insert
Delete
O(log n)
O(log n)
O(log n)
Die Komplexität für Search ergibt sich auf folgenden Lemma: AVL-Bäume mit der Höhe h haben
mindestens Fib(h + 2) Blätter, also Fib(h + 2) − 1 interne Knoten. Es gilt
√ !n
1± 5
1
Fib(n) ≈ √
2
5
Daher gilt, dass AVL-Bäume mit n Knoten die Höhe O(log n) haben, womit dies auch für Search
gilt. Bei Insert und Delete müssen u. U. bestimmte Rebalancierungen durchgeführt werden, deren
Worst-Case-Laufzeit aber immer O(log n) ist.
9.3.26
Wovon hängt die Zahl der speicherbaren Element im AVL-Baum ab?
Von seiner Höhe.
9.3.27
Vergleichen Sie die verschiedenen Heap-Implementierungen hinsichtlich der Laufzeiten.
Make-Heap
Insert
Minimum
Extract-Min
Merge
Decrease-Key
Delete
9.3.28
Binary Heap
O(1)
O(log n)
O(1)
O(log n)
O(n)
O(log n)
O(log n)
Binomial Heap
O(1)
O(log n)
O(log n)
O(log n)
O(log n)
O(log n)
O(log n)
Fibonacci Heap
O(1)
O(1)
O(1)
O(log n)
O(1)
O(1)
O(log n)
Was zeichnet eine sich selbst organisierende Liste aus?
Selbstorganisierende Listen verändern die Position der Element entsprechend ihrer Zugriffshäufigkeit um
die Zugriffszeiten für häufig benutzte Elemente zu verbessern. Es kommen zwei verschiedene Heuristiken
zum Einsatz:
1. Move-To-Front Rule (MFR): Bei jedem Zugriff auf ein Element wird dieses an den Anfang der Liste
verschoben. Für die MFR gilt, dass die amortisierten Kosten höchstens um den Faktor 2 schlechter
sind als ein optimaler Listenalgorithmus.
2. Transposition Rule (TR): Bei jedem Zugriff auf ein Element wird dieses um eine Position nach
vorne verschoben. Die TR kann verglichen mit der MFR oder einem optimalen Algorithmus beliebig
schlecht werden.
9.3.29
Was ist ein Leftist-Baum?
Ein Leftist-Baum ist ein binärer Suchbaum, so dass für jeden Knoten gilt, dass ein kürzester Weg zu
einem Blatt über ein rechtes Kind führt.
9.3.30
Nennen Sie ein Beispiel für sich selbst organisierende Datenstrukturen?
Selbst-Organisierende-Listen und Splay-Trees.
9.3.31
118
Ist ein Splay-Tree für eine Englischlexikon geeignet?
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.3. Datenstrukturen
Nur wenn man aus irgendwelchen Gründen andauernd die gleichen Wörter nach schaut.
9.3.32
Gibt es Datenstrukturen die Mengenoperationen effizient unterstützen?
Ja, Union-Find-Strukturen.
9.3.33
Wie funktionieren Radix-Heaps?
Radix-Heaps greifen die Idee von 1-Level Buckets auf, wieder muss die maximale Differenz der Schlüssel
C bekannt sein. Im Gegensatz zu den 1-Level Buckets werden bei Radix-Heaps keine festen Bucketgrössen sondern Bucket mit exponentiell zunehmender Grösse verwendet. Dadurch werden nur noch
O(log c) Buckets benötigt. Da auch bei den Radix-Heaps die Laufzeit für die teure Extract-Min
Operation
√ von der Anzahl der Buckets abhängt, verbessern sich die amortisierten Kosten von O(C)
bzw. O( C) auf O(log C).
9.3.34
Was sind balancierte Bäume?
Suchbäume ohne Balancierung können aus der Form geraten bzw. entarten wobei sich die Laufzeiten
für die Zugriffe drastisch verschlechtern können. Balancierte Bäume haben Mechanismen, die dafür
sorgen, dass die Bäume nicht oder nur wenig entarten.
9.3.35
Was sind 1-Level Buckets?
Buckets bieten eine Möglichkeit Priority Queues zu implementieren. Die Voraussetzung für die Bucket
basierten Implementierungen sind:
Die Schlüssel sind ganzzahlig.
Zu jedem Zeitpunkt gilt, dass die Differenz des grössten und kleinsten Schlüssels ≤ c ist.
Dies ist z. B. beim Algorithmus von Dijkstra erfüllt. c ist hier die maximale Kantenlänge.
1-Level Buckets bestehen aus
einem Array b[0 . . . C + 1] zur Aufnahme der Buckets. Jedes bi enthält einen Pointer auf die Liste
der Elemente im Bucket,
einer Zahl minvalue, die gleich dem kleinsten gespeicherten Schlüssel ist,
eine Zahl 0 ≤ minpos ≤ c, die den Index des Buckets mit dem kleinsten Schlüssel enthält und
einer Zahl n, die die Anzahl der gespeicherten Elemente hält.
Die Priority Queue Operationen sind dann wie folgt implementiert.
Insert (x). Das Element x wird in b[key(x) mod (C + 1)] eingefügt. Falls key(x) kleiner als
der bisher kleinste Wert ist, müssen minvalue und minpos angepasst werden. Ausserdem wird n
inkrementiert. Die Laufzeit für diese Operation ist O(1).
Extract-Min. n wird decrementiert. Falls noch Elemente übrig bleiben, muss das neue kleinste
Element gesucht werden und alle Variablen angepasst werden. Dazu müssen alle Buckets durchlaufen werden. Die Laufzeit ist O(C)
Decrease-Key. Zuerst wird der Schlüssel verkleinert. Ergibt sich dadurch ein neuer minvalue,
müssen die Variablen angepasst werden. Laufzeit ist O(1).
9.3.36
Was sind 2-Level Buckets?
Wenn der Wertebereich sehr gross im Verhältnis zu der Anzahl der abgelegten Werte ist, sind 1-Level
Bucket aus zwei Gründen ungünstig.
Das Array b belegt statischen Speicherplatz der Grösse O(C) obwohl nur ein kleiner Teil davon
gebraucht wird.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
119
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
Der Zeitbedarf für Extract-Min nähert sich der Worst-Case-Komplexität von O(C), da der
nächste nicht-leere Bucket ziemlich weit entfernt sein kann.
2-Level Buckets versuchen dieses Problem zu beheben,
in dem sie eine Bucket-Hierarchie einführen.
√
Es gibt ein Top-Bucket (btop) bestehend aus | C + 1|√Buckets und zu jedem Bucket in btop gibt es
ein weiteres Bottom-Bucket (bbot), das auch aus B = | C + 1| Buckets besteht. Das i-te bbot nimmt
Elemente auf deren Schlüssel im Intervall [iB, (i+1)B] liegen. Um ein Element in ein Bucket einzufügen
wird zuerst das passende Bucket in btop gesucht. Dann wird in dem dazugehörigen bbot das Element
eingefügt.
Um sowohl Zeit als auch Platz zu sparen, kann man durch leichte Modifikation
√ nur ein einziges BottomBucket einsetzen. Dann benötigt man nur zwei Arrays der Länge B = | C + 1| + 1. Dabei enthält
das Top-Bucket die meisten Elemente in grob vorsortierter Form, nur die Elemente mit den kleinsten
Schlüsseln werden im Bottom-Bucket gehalten. Mit√dieser Implementierung erreicht man Laufzeiten
von O(1) für Insert sowie Decrease-Key und O( C) für Extract-Min.
9.4
Selektieren und Sortieren
9.4.1
Stellen Sie sich vor, Sie haben ein Feld und wollen das 15. grösste finden. Wie können Sie effektiver als
mit Sortieren vorgehen.
Mit einem Selektionsalgorithmus.
9.4.2
Wie viele Vergleiche braucht man um von n-Element das Grösste zu finden?
Man braucht auf jeden Fall n − 1 Vergleiche. Beweis: Man Betrachte den Algorithmus als Folge von
Spielen, die immer das grössere Element gewinnt. Jeder Spieler ausser dem Gewinner muss mindestens
einmal verlieren, daher n − 1 Vergleiche.
9.4.3
Welche Komplexität hatte eine naive Bestimmung des Medians?
Man verwendet eine normalen Sortieralgorithmus und wählt das mittlere Element. Laufzeit: O(n log n)
9.4.4
i Nennen Sie einen Algorithmus zur effizienten Bestimmung des Median.
BFPRT.
9.4.5
Wie ist die untere Schranke für die Median-Bestimmung (mit Beweis)?
− 2 Vergleiche. Der Beweis läuft über das Gegenspielerargument.
Die untere Schranke is 3n
2
9.4.6
Erklären Sie Radix-Sort.
Die Idee bei Radix-Sort ist die Eingabewerte einzeln nach ihren Dezimalstellen zu sortieren und zwar
zuerst nach der niedrigsten. Das müssen natürlich nicht Dezimalstellen sein, es können auch Buchstaben
oder Binärzahlen verwendet werden. Das Beispiel zeigt wie 3-stellige Dezimalzahlen zuerst nach den
Einern , dann nach Zehnern und zuletzt nach den Hundertern sortiert werden.
329
720
720
329
457
355
329
355
657
436
436
436
839
457
839
457
⇒
⇒
⇒
436
657
355
657
720
329
457
720
355
839
657
839
↑
↑
↑
120
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.4. Selektieren und Sortieren
Die Laufzeit von Radix-Sort hängt natürlich von dem Algorithmus ab, der zum Sortieren nach den
einzelnen Stellen verwendet wird. Um n Zahlen nach einer Stelle zu sortieren benötigt man z. B. mit
Mergesort O(n log n) Zeit. Falls die Zahlen d Stellen haben, benötigt man insgesamt O(d · n log n), also
keine Vorteile zu normalen Sortieralgorithmen. Wenn allerdings ein nicht-vergleichsbasierter Algorithmus wie Counting Sort mit linearer Laufzeit verwendet wird, ergibt sich auch eine lineare Gesamtlaufzeit
von Radix-Sort.
9.4.7
Erklären Sie Bucket-Sort.
Wenn für alle zu sortierenden Zahlen x, gilt, dass 0 ≤ x < 1 und die Zahlen zufällig verteilt sind, kann
Bucket-Sort ein Array mit n Zahlen in Zeit O(n) sortieren. Benötigt werden n Buckets, die jeweils eine
Liste von Werte aufnehmen können. Der Algorithmus läuft dann wie folgt ab.
1. Initialisiere Buckets b0 , b1 , . . . , bn−1 .
2. Lege ai in Bucket dn · ai e.
3. Sortiere die Elemente innerhalb der Buckets.
4. Konkateniere die Buckets.
Bis auf den Schritt 3 ist alles in O(n) zu erledigen. In Schritt 3 kommt es darauf an, wie wie viele
Elemente durchschnittlich in einem Bucket sind. Falls in jedem Bucket nur 1 Elemente ist, ist es
einfach. Sei ni die Zufallsvariable die die Anzahl der Element in Bucket i beschreibt. Wenn man in
Schritt 3 einen Sortieralgorithmus mit quadratischer
Laufzeit verwendet, ist die erwartete Zeit, die
Element im Bucket i zu sortieren E O(n2i ) = O(E n2i ). Für alle Bucket ergibt sich daher die Summe:
!
n−1
n−1
X X
2 (9.1)
E n2i
O E ni = O
i=0
i=0
Die Wahrscheinlichkeit, dass ein Element x in Bucket i landet ist 1/n. Das Verteilen von n Elementen
auf n Buckets kann mit dem Bällen-Urnen-Modell erfasst werden und ist binomialverteilt. Das heisst
die Wahrscheinlichkeit, dass ni = k ist, folgt der Binomialverteilung b(k; n, p). Somit gilt für den
Erwartungswert und die Varianz
1
=1
n
E [ni ]
=
np = n ·
Var [ni ]
=
np(1 − p) = n ·
1
1
1
=1−
· 1−
n
n
n
Für jede Zufallsvariable gilt folgende Gleichung
2
E n2i = Var [ni ] + E [ni ]
Daraus ergibt sich
E n2i
1
+ 12
n
1
= 2−
n
= O(1)
= 1−
Wenn man dieses Ergebnis nun in (9.1) einsetzt ergibt sich
n−1
X
O E
i=0
n2i
=O
n−1
X
i=0
O(1)
!
und damit eine Gesamtlaufzeit von O(n).
9.4.8
Was versteht man unter Selektion?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
121
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
Das Suchen eines n kleinsten Elements in einer Menge.
9.4.9
Warum sortiert man nicht einfach?
Sortieren hat grösseren Aufwand als Selektieren.
9.4.10
Wie funktioniert Quicksort?
Quicksort ist ein Divide&Conquer Algorithmus mit einer durchschnittliche Laufzeit von O(n log n). Die
Worst-Case-Laufzeit ist allerdings O(n2 ). Der grundlegende Algorithmus ist sehr einfach und funktioniert wie folgt. Dieser Algorithmus sortiert das Array A[p . . . r].
Quicksort(A, p, r)
1 if p < r
2
then q ← Partition(A, p, r)
3
Quicksort(A, p, q)
4
Quicksort(A, q + 1, r)
Das Eingabearray wird in zwei Teile zerlegt und diese rekursiv mit Quicksort sortiert. Entscheidend ist
die Partitionierung des Arrays. Eine einfache Implementierung von Partition funktioniert so.
Partition(A, p, r)
1 x ← A[p]
2 i←p−1
3 j ←r+1
4 while (True) {
5
do j ← j − 1 until (A[j] ≤ x)
6
do i ← i + 1 until (A[i] ≥ x)
7
if (i < j) swap A[i] ↔ A[j]
8
else return j
9 }
Die Funktion Partition wählt eine Pivot-Element x und vertausche die Array-Elemente so, dass alle
Element links von x kleiner und alle rechts davon grösser sind als x. Dafür werden zwei Zeiger i und
j verwendet, die gegeneinander laufen. Der entscheidende Punkt ist die Wahl des Pivot-Elements. In
dieser Implementierung wird einfach das erste Element des Arrays gewählt. Diese Methode ist nicht
optimal. Wenn das Array z. B. bereits sortiert ist ergeben sich bei dieser Wahl immer 1:(n − 1)–
Partitionen. Deshalb konzentrieren sich die Verbesserungen von Quicksort darauf das Pivot-Element
möglichst geschickt zu wählen. Mann kann es zufällig wählen oder noch besser den Median von drei
Zufallswerten wählen. Zur Analyse von Quicksort, siehe 9.4.16.
9.4.11
i Wie funktioniert Mergesort?
Mergesort ist ein Divide&Conquer Algorithmus. Eine Feld wird sortiert in dem es in zwei (fast) gleich
grosse Teilfelder zerlegt wird, die dann wieder rekursiv mit Mergesort sortiert werden. Die Teilfelder
werden dann geMerget um die Gesamtlösung zusammen zu setzen.
Divide: Teile das n-elementige, zu sortierende Feld in zwei Teilfelder der Länge n/2.
Conquer: Sortiere die zwei Teilfelder rekursiv mit Mergesort.
Combine: Verschmelze die zwei sortierten Teilfelder zu einem.
Das Verschmelzen der Teilfelder erledigt die Funktion Merge. Anschaulich funktioniert sie wie ein der
Algorithmus, den ein Mensch benutzen würde um zwei sortierte Kartenstapel zu verschmelzen. Beide
Stapel liegen mit der kleinsten Karte oben auf dem Tisch. Man wählt nur immer die kleinste Karte die
oben aufliegt und legt sie nacheinander auf einen dritten Stapel. Der dritte Stapel ist dann eine korrekte
Verschmelzung der beiden Stapel. Dieser Algorithmus lässt sich in O(n) implementieren, wobei n die
Summe der Längen der beiden Teilfelder ist. Mit der Merge-Funktion sieht der Mergesort-Algorithmus
so aus:
122
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.4. Selektieren und Sortieren
Merge-Sort(A, p, r)
1 if p < r
2 then q ← b(p + r)/2c
3
Merge-Sort(A, p, q)
4
Merge-Sort(A, q + 1, r)
5
Merge(A, p, q, r)
Diese Funktion sortiert das Teilfeld A[p . . . r]. Falls p > r gibt es nicht mehr zu sortieren und die
Funktion bricht ab. Merge (A, p, q, r) verschmelzt die Felder A[p . . . q] und A[q + 1 . . . r].
9.4.12
i Komplexität von Mergesort herleiten.
Mergesort ist ein typischer Divide&Conquer-Algorithmus. Die Laufzeit T (n) von Divide&ConquerAlgorithmen kann rekursiv ausgedrückt werden:
O(1)
wenn n ≤ c ,
T (n) =
αT (n/β) + D(n) + C(n) sonst.
Wobei c eine konstante ist, für die die Berechnung trivial wird. Das Problem wird in α Teilproblem
geteilt und des Teilproblem hat die Grösse n/β, d. h. das die Teilprobleme sich auch überlappen können.
D(n) ist die Zeit, die man braucht um das Problem in Teilprobleme zu zerlegen, C(n) die Zeit um die
Lösung aus den Teillösungen zusammenzusetzen.
Die Rekursion für Mergesort ergibt sich wie folgt:
Divide: Dieser Schritt muss die Mitte des Subarrays finden, daher D(n) = O(1).
Conquer: Das Problem wird rekursiv in 2 Teilprobleme zerlegt, die beide die Grösse n/2 haben,
also 2T (n/2).
Combine: Merge benötigt für n Elemente O(n), also C(n) = O(n).
Daraus ergibt sich:
T (n) =
O(1)
2T (n/2) + O(n)
wenn n = 1 ,
sonst.
Der erste Fall ergibt sich, weil ein Feld der Länge 1 bereits sortiert ist. Das O(1) für Divide trägt
zur Summe nichts bei, also fällt es unter den Tisch. Für diese Rekursionsgleichung kann nun mit dem
Mastertheorem (9.1.6) die Laufzeit bestimmt werden. α = 2, β = 2 und f (n) = O(n), daher trifft der
zweite Fall des Mastertheorems zu und die Laufzeit von Mergesort ist
Θ nlogβ α log n = Θ(n log n) .
9.4.13
Wie funktioniert Heapsort?
Die n zu sortierenden Element werden nacheinander auf den Heap gelegt. Danach werden alle n Element
wieder mit Extract-Min herunter geholt. Dies kann auch in-situ geschehen. Laufzeit ergibt sich aus
den Laufzeiten der Heapoperationen und ist O(n log n).
9.4.14
Wie funktioniert BFPRT?
Der Algorithmus Select zur Bestimmung des i-kleinsten Elements einer Menge S, läuft in folgenden
Schritten ab.
1. Teile die n Elemente in bn/5c Gruppen zu je 5 Elementen plus eine Gruppe mit n mod 5 Elementen.
2. Jetzt wird der Median jeder der dn/5e Gruppen bestimmt in dem die Elemente der Gruppen per
Insertion Sort sortiert werde und der mittlere Wert gewählt wird. Falls die Gruppe ein ungerade
Anzahl an Elementen hat, wird der grössere der beiden Medianwerten gewählt.
3. Jetzt wird Select rekursiv aufgerufen um den Median der in Schritt 2 berechneten Median zu
bestimmen.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
123
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
4. Jetzt werden die Element des Eingabearrays bzgl. des Medians der Mediane s partitioniert. Dadurch
ergeben sich zwei Mengen S1 = {x ∈ S | x < s} und S2 = {x ∈ S | x > s}
5. Jetzt gibt es drei Fälle:
Falls i ≤ |S1 |, bestimme rekursiv das i-kleinste Element in S1
Falls i = |S1 | + 1, gib s als Lösung zurück.
Sonst, bestimme rekursiv das (i − |S1 | − 1)-kleinste Elemente in S2 .
9.4.15
Wie ist die Laufzeit von BFPRT?
Um die Laufzeit zu bestimmen, muss man zuerst eine untere Grenze für die Elemente, die grösser als
das Partitionierungselement s sind, bestimmen. Mindestens die Hälfte der Mediane, die in Schritt 2
gefunden werden, ist grösser oder gleich dem Median der Mediane s. Also sind aus der Hälfte der dn/5e
Gruppen jeweils drei Element grösser als s. Ausnahmen sind die Gruppe, die s enthält und die letzte
Gruppe, falls n nicht durch 5 teilbar ist. Wenn man diese beiden Gruppen weg lässt, ergibt sich für die
Anzahl der Elemente, die grösser als s ist
l m
3n
1 n
− 6.
−2 ≥
3
2 5
10
Ebenso gilt, dass die Anzahl der Elemente, die kleiner als s sind, mindestens 3n/10 − 6 ist. Daher
wird im Worst-Case Select 7n/10 + 6 mal rekursiv aufgerufen (Schritt 5). Die in der Abbildung grau
unterlegten Elemente sind die, die grösser als s sind.
s
Damit lässt sich nun eine Rekursionsgleichung erstellen. Schritt 1, 2 und 4 benötigen O(n). Schritt 3
benötigt T (dn/5e) und Schritt 5 benötigt höchstens T (7n/10 + 6). Für n > 20 gilt 7n/10 + 6 < n und
für n ≤ 80 ist die Laufzeit O(1). Daher ergibt sich die Rekursionsgleichung:
O(1),
wenn n ≤ 80,
T (n) ≤
T (dn/5e) + T (7n/10 + 6) + O(n) wenn n > 80.
Die lineare Laufzeit wird nun durch die Substitutionsmethode gezeigt. Man nimmt an, dass T (n) ≤ cn
ist und Substitute entsprechend.
T (n)
≤ cdn/5e + c(7n/10 + 6) + O(n)
≤ cn/5 + c + 7cn/10 + 6c + O(n)
≤ 9cn/10 + 7c + O(n)
≤
cn
Der letzte Schritt gilt, da man c so gross wählen kann, dass es grösser als O(n) für alle n > 80 ist.
9.4.16
Rekursionsformel für Quicksort?
Die Rekursionsformel hängt von der Güte der Partitionierung ab.
Im schlechtesten Fall teil Quicksort immer in eine Partition der Grösse 1 und eine Partition der
Grösse n − 1. Dann ergibt sich
T (n) = T (n − 1) + O(n)
und dafür gilt T (n) = O(n2 ).
124
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.4. Selektieren und Sortieren
Im besten Fall teil Quicksort immer in zwei Partitionen der Grösse n/2 auf, dann gilt
T (n) = 2T (n/2) + O(n)
was laut Master Theorem O(n log n) ist.
Falls Quicksort in jedem Schritt zwei Partitionen, deren Grössen konstant proportional zueinander
sind (z. B. immer 9:1), erzeugt, so ergibt sich die Rekursionsgleichung
T (n) = T (9n/10) + T (n/10) + O(n)
(für das Beispiel)
Egal wie diese Verhältnis aussieht, also z. B. auch 99:1, ergibt sich die Laufzeit O(log n), weil der
Rekursionsbaum immer Tiefe O(log n) hat und jede Ebene O(n) kostet. Daher ergibt sich auch
für die durchschnittliche Laufzeit von Quicksort O(n log n). Mann muss nur dafür sorgen, dass die
Partitionierung möglichst zufällig abläuft.
9.4.17
Gibt es Sortierverfahren mit einer besseren Laufzeit als O(n log n).
O(n log n) ist die untere Schranke für vergleichsbasiertes Sortieren. Wenn ohne Vergleiche sortiert wird,
können bessere Laufzeiten erreicht werden. Beispiele sind Radix- und Bucket-Sort die aber bestimmte
Annahmen über die Daten machen.
Die untere Schranke für vergleichsbasiertes Sortieren kann über den Entscheidungsbaum hergeleitet
werden. Wenn n Element sortiert werden müssen, gibt es n! verschieden Permutationen, also hat der
Entscheidungsbaum n! Blätter. Die Länge des längsten Pfades von der Wurzel zu einem Blatt entspricht
der Worst-Case-Laufzeit beim Sortieren. Deshalb muss man nur die Höhe h des Baumes bestimmen um
die untere Schranke für Sortieren zu finden. Da ein Binär (Entscheidungsbaum ist binär) nicht mehr
als 2h Blätter hat gilt
n! ≤ 2h .
Daraus ergibt sich durch Logarithmieren
h ≥ log n! .
Mit der Stirling-Approximation für die Fakultät kommt man zu
h
≥
=
=
=
9.4.18
log
n n
e
n log n − e log e
n log n − O(1)
O(n log n)
Braucht Quicksort zusätzlichen Speicher?
Ausser ein paar wenigen Zeigern, nein.
9.4.19
Wie kann man bei Quicksort die Worst-Case-Laufzeit vermeiden?
Mann muss dafür sorgen, dass die Partitionierung möglichst gut ist und nicht in zwei Partitionen teilt,
bei der eine Partition nur die Grösse 1 hat. Dazu kann man eine randomisierte Version benutzten, die
das Pivot-Element immer zufällig auswählt. Das kann noch weiterhin verbessert werden, wenn man 3
Element zufällig wählt und den Median dieser als Pivot-Element verwendet (Median-of-Three).
9.4.20
Warum verwendet man in der Praxis Mergesort häufiger?
Mergesort sortiert Elemente, die bereits richtig sind, nicht.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
125
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
9.5
Minimale Spannbäume
9.5.1
Wie funktioniert der Algorithmus von Kruskal?
Der Algorithmus von Kruskal ist ein Greedy-Algorithmus zur Bestimmung eines minimalen Spannbaumes. Der Algorithmus sortiert die Kanten nach ihrem Gewicht und fängt dann mit der kleinsten Kante
an diese in den Spannbaum einzufügen. Bei jedem Einfügen überprüft er, ob durch das Einfügen ein
Kreis entsteht, falls ja, wird die Kante ignoriert, falls nein, wird die Kante eingefügt.
Meist wird der Algorithmus nicht mit einer Kantenvorsortierung sondern einer Priority-Queue implementiert. Dies kann Vorteile haben, wenn die grössten Kanten des Graphen nicht Teil des minimalen
Spannbaums sind. Bei der Implementierung mit Priority-Queue kann der Algorithmus in diesem Fall
frühzeitig abbrechen.
Zur Kreisüberprüfung wird eine Union-Find-Struktur verwendet. Zu Beginn ist jeder Knoten in einer
eigenen Menge. Wenn eine Kante eingefügt werden soll, wird überprüft, ob die beiden Endknoten in
unterschiedlichen Menge liegen, wenn nicht, wird die Kante ignoriert. Falls dem so ist, wird die Kante
eingefügt und die beiden Mengen verschmolzen.
Implementierung mit PQ:
Kruskal
01 A ← ∅
02 Q ← E[G]
03 for each (vertex v ∈ V [G]) {
04
Make-Set(v)
05 }
06 while (Q 6= ∅) {
07
(u, v) ← Extract-Min(Q)
08
if (Find-Set(u) 6= Find-Set(v)) {
09
A ← A ∪ {(u, v)}
10
Union(u, v)
11
}
12 }
13 return A
Dieser Algorithmus hat gegenüber dem mit Kantenvorsortierung keinen Vorteil, da er nicht frühzeitig
abbricht. Theoretisch kann man abbrechen, wenn nur noch eine einzige Menge übrig ist, dann kann
sowieso keine weitere Kante mehr hinzugefügt werden. Für die Priority-Queue Operationen ergibt sich
die Laufzeit O(m log m), die Union-Find-Operationen haben eine sehr kleine (amortisierte) Komplexität
und tragen damit unerheblich zu der Gesamtlaufzeit bei, also hat der Algorithmus von Kruskal die
Laufzeit O(m log m).
9.5.2
Wie ist der Dijkstra-Algorithmus mit dem von Prim vergleichbar?
Es handelt sich praktisch um den gleichen Algorithmus. Bei Dijkstra müssen zusätzlich die Pfadlängen
von Startpunkt addiert werden.
9.5.3
Welche Algorithmen gibt es zur Berechnung minimaler Spannbäume?
Es gibt die Algorithmen von Kruskal und Prim.
9.5.4
Erklären Sie den Algorithmus von Prim.
Der Algorithmus von Prim zur Bestimmung es minimalen Spannbaums geht wie folgt vor. Alle Knoten
des Baumes werden in einer Priority Queue verwaltet. Zu Beginn erhalten alle Knoten den Wert ∞, nur
der Startknoten erhält 0. Nun nimmt man sich den Knoten u mit dem kleinsten Wert aus der Queue
(beim ersten mal der Startknoten) und durchläuft man alle Nachbarknoten v des Knotens u, die noch
in der Queue sind. Ist das Kantengewicht von (u, v) kleiner als der beim Knoten gespeicherte Wert
key[v], wird der Knotenwert aktualisiert.
126
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.6. Kürzeste Pfade
Prim (G, w, r)
01 Q ← V [G]
02 for each (u ∈ Q) {
03
key[u] ← ∞
04 }
05 key[r] ← 0
06 π[r] ←NIL
07 while (Q 6= ∅) {
08
u ← Extract-Min(Q)
09
for each (v ∈ Adj[u]) {
10
if (v ∈ Q ∧ w(u, v) < key[v]) {
11
π[v] ← u
12
key[v] ← w(u, v)
13
}
14
}
15 }
Der Algorithmus speichert zusätzlich für jeden Knoten seinen Vorgänger im Feld π[].
Laufzeit: Die Schleife in den Zeilen 7–15 wird n mal durchlaufen, darin wird jedes mal ein ExtractMin ausgeführt, also n log n. Die Schleife in den Zeilen 9–13 wird O(m) mal durchlaufen. Also ergibt
sich insgesamt O(m+n log n). Dies gilt nur, wenn die Priority Queue mit Fibonacci Heaps implementiert
wird, da bei diesen die Zuweisung in Zeile 12 in O(1) durchgeführt werden kann.
9.5.5
Was ist ein Spannbaum?
Für einen Graphen G(V, E) ist G0 (V, E 0 ) mit E 0 ⊆ E ein Spannbaum, wenn G0 ein Baum ist.
9.5.6
Was ist eine minimaler Spannbaum, was hat er für einen praktischen Nutzen?
Ein minimaler Spannbaum ist ein Spannbaum des Kantengewicht (Summe der Gewichte aller Baumkanten) minimal ist. In der Praxis kann man so z. B. die billigste Leitungskonfiguration zwischen Rechnern
finden, so dass diese gerade noch verbunden sind.
9.5.7
Was sind die
blaue und die
rote Regel?
Diese Regeln werden bei den Korrektheitsbeweisen für minimale Spannbaum Algorithmen benutzt.
9.6
Kürzeste Pfade
9.6.1
i Wie funktioniert Algorithmus von Dijkstra?
Dijkstras Algorithmus zur Bestimmung der kürzesten Pfade ähnelt dem von Prim zur Bestimmung
des minimalen Spannbaumes sehr stark. Wieder werden alle Knoten in einer Priority Queue verwaltet
und ihr Entfernungswert zu Beginn auf ∞ gesetzt. Der Startknoten erhält den Wert 0. Nun wird der
kleinsten Knoten u aus der Queue entnommen und alle seine Nachbarn v durchlaufen. Gibt es von u
nach v einen kürzeren Weg als in v gespeichert, wird der Wert bei v aktualisiert.
Dijkstra (G, w, s)
01 for each (v ∈ V [G]) {
02
d[v] ← ∞
03
π[v] ←NIL
04 }
05 d[s] ← 0
06 Q ← V [G]
07 while (Q 6= ∅) {
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
127
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
08
09
10
11
12
13
14
15
}
u ← Extract-Min(Q)
for each (v ∈ Adj[u]) {
if (d[v] > d[u] + w(u, v)) {
d[v] ← d[u] + w(u, v)
π[v] ← u
}
}
Der Algorithmus speichert zusätzlich für jeden Knoten seinen Vorgänger im Feld π[].
Laufzeit: Auch hier zeigt sich die Verwandtschaft zum Algorithmus von Prim. Die Schleife in den
Zeilen 7–15 wird n mal durchlaufen, darin wird jedes mal ein Extract-Min ausgeführt, also n log n.
Die Schleife in den Zeilen 9–13 wird O(m) mal durchlaufen. Also ergibt sich insgesamt O(m + n log n).
Dies gilt nur, wenn die Priority Queue mit Fibonacci Heaps implementiert wird, da bei diesen die
Zuweisung in Zeile 11 in O(1) durchgeführt werden kann.
9.6.2
Was ist das Single-Source-Shortest-Path-Problem?
Man möchte die Entfernung von einem Startknoten zu allen anderen Knoten wissen.
9.6.3
Komplexität von Dijkstra?
Es werden n−1 Schritte gemacht in denen jeweils eine Extract-Min- und für alle Nachbarn des Knoten
evtl. eine Insert- oder Decrease-Key-Operation durchgeführt. Wenn die PQ mit Fibonacci-Heaps
implementiert ist, beträgt die Laufzeit O(n log n + m).
9.6.4
Welche Verfahren zur Bestimmung der transitiven Hülle kennen Sie?
Man kann alle Kantengewichte auf 1 setzen und den Floyd-Warshall-Algorithmus laufen lassen. Gibt
es einen Pfad zwischen zwei Knoten steht in der Matrix eine Zahl n ansonsten ∞.
9.6.5
Nennen Sie mir einen Algorithmus zur effizienten Matrizen-Multiplikation.
Der Strassen-Algorithmus.
9.6.6
Welche Algorithmen gibt es ausser Dijkstra für SSSP?
Bellman-Ford.
9.6.7
Welche Algorithmen gibt es für das All-Pairs-Shortest-Path-Problem?
Floyd-Warshall.
9.6.8
Wie kann man den Floyd-Warshall-Algorithmus so modifizieren, dass man auch die Pfade ablesen kann?
Man kann in einer Vorgängermatrix für jeden Knoten den Vorgänger speichern.
9.6.9
Welche Komplexität hat der Floyd-Warshall-Algorithmus?
Er Algorithmus besteht aus 3 ineinander geschachtelten For-Schleifen und daher Laufzeit O(n 3 ). Der
Algorithmus ist dem CYK-Algorithmus sehr ähnlich, der dieselbe Laufzeit hat.
9.6.10
Wie kann man Zyklen in Graphen bestimmen?
Ein Graph enthält genau dann Zyklen, wenn während der Tiefensuche Rüeckwärtskanten gefunden
werden.
128
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
9.7. Matchings
9.6.11
i Erklären Sie den Strassen-Algorithmus zur Matrizen-Multiplikation.
Normalerweise wird die Multiplikation zweier n × n Matrizen wie folgt berechnet.
b11 b12
a11 a12
c11 c12
·
=
b21 b22
a21 a22
c21 c22
a11 b11 + a12 b21 a11 b12 + a12 b22
=
a21 b11 + a22 b21 a21 b12 + a22 b22
Das Kostet 8 Multiplikation (O(n3 )) und 4 (O(n2 )) Additionen. Wenn man einen Divide&ConquerAlgorithmus angibt, der die n × n Matrizen immer wieder in n/2 × n/2 Matrizen zerlegt und dabei die
klassische Form der Berechnung anwendet, erhält man die Rekursionsformel
T (n) = 8T (n/2) + O(n2 )
Laut Mastertheorem gilt für T (n) = O(n3 ). Also wurde durch Divide&Conquer nichts gewonnen, im
Vergleich zur normalen Matrizen-Multiplikation. Bei Strassens Methode wird die Anzahl der Multiplikationen auf 7 gedrückt. Man geht wie folgt vor. Zuerst werden sieben Produkte gebildet.
m1
m2
m3
:=
:=
:=
m4
m5
:=
:=
m6
m7
:=
:=
c1
=
c2
c3
c4
=
=
=
(a12 − a22 )(b21 + b22 )
(a11 + a22 )(b11 + b22 )
(a12 − a21 )(b11 + b12 )
(a11 + a12 )b22
a11 (b12 − b22 )
a22 (b21 − b11 )
(a21 + a22 )b11
Mit diesen Produkten ergibt sich:
m 1 + m2 − m4 − m6
m 4 + m5
m 6 + m7
m 2 − m3
Wenn der Divide&Conquer-Algorithmus Strassens Methode verwendet, ergibt sich
T (n) = 7T (n/2) + O(n2 )
und für das gilt laut Mastertheorem T (n) = O(nlog 7 ) = O(n2,81 ). Der Algorithmus von Strassen ist
also tatsächlich schneller.
9.7
Matchings
9.7.1
Was ist ein Matching?
Eine Matching ist eine Kantenmenge, wobei kein Knoten Endpunkt von mehr als einer Kante ist.
9.7.2
Welche Matchings sind interessant?
Interessant sind Matchings mit maximaler Kardinalität. Gibt es mehrere solche Matchings interessiert
man sich für Matchings maximaler Kardinalität mit minimalen bzw. maximalen Gewicht.
9.7.3
Wie findet man Matchings?
Man sucht nach augmentierenden Pfaden. Solange es noch einen augmentierenden Pfad gibt, kann man
diesen Invertieren und erhöht damit die Kardinalität des Matchings. Wenn es keine augmentierenden
Pfade mehr gibt, ist die Kardinalität des Matchings maximal.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
129
Kapitel 9. Effiziente Algorithmen und Datenstrukturen
9.7.4
Was ist ein augmentierender Pfad? Wie findet man ihn?
Ein augmentierender Pfad ist ein Pfad dessen Kanten abwechselnd gemacht und ungematcht sind. Die
erste und die letzte Kante müssen ungematcht sein.
Im bipartiten Graphen können augmentierende Pfade mit einer modifizierten Breitensuche gefunden
werden.
130
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
Kapitel 10
Automaten, Formale Sprachen und
Berechenbarkeit
10.1
10.1.1
Allgemeines
i Was ist die Chomsky-Hierarchie?
Eine hierarchische Einteilung formaler Sprachen.
10.1.2
Möglichkeiten Sprachen zu Erzeugen?
Grammatiken und Turing-Generator-Maschinen.
10.1.3
Was ist Abzählbarkeit?
Eine unendliche Menge M ist abzählbar wenn es eine bijektive Abbildung von N nach M gibt:
M = {f (1), f (2), f (3), . . .}
Diese Funktion muss nicht zwangsweise berechenbar sein.
10.1.4
Kann man aus einer Grammatik schliessen, was für ein Sprachtyp beschrieben wird?
Ja. Die Produktion der verschiedenen Sprachtypen unterliegen bestimmten Regeln.
10.1.5
Was ist der Homomorphismus bei formalen Sprachen?
Wie Schnitt, Vereinigung, usw. ist auch ein Homomorphismus eine Operation auf formalen Sprachen.
Sei h : Σ → ∆∗ eine Abbildung, also Zeichen → Zeichenkette. Man kann die Abbildung zu einem
Homomorphismus h : Σ∗ → ∆∗ erweitern, also Zeichenkette → Zeichenkette. Die folgenden Schritte
Zeigen die zeichenweise Anwendung der Abbildung.
h()
h(a)
h(aw)
= = h(a)
= h(a)h(w)
Für eine Sprache L ⊆ Σ∗ heisst h = {h(w) | w ∈ L} ⊆ ∆∗ homomorphes Bild von L. Entsprechend ist
(−1)
h
= {x ∈ Σ∗ | h(x) = w, w ∈ L} das Urbild einer Sprache L ⊆ ∆∗ . Man nennt h
Homomorphismus.
10.1.6
(−1)
den inversen
Was sind Äquivalenzklassen? Was haben Sie mit formalen Sprachen zu tun?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
131
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
Jede Äquivalenzrelation R teilt eine Menge in mehrere disjunkte Mengen. Die Anzahl dieser Mengen
heisst der Index von R. Man kann jeder Sprache die Äquivalenz Relation RL auf Σ∗ zuweisen. Es gilt
xRL y genau dann, wenn für alle Wörter z ∈ Σ∗ gilt
xz ∈ L ⇔ yz ∈ L
Der Satz von Myhill, Nerode besagt, dass eine Sprache genau dann regulär ist, wenn der Index der
von RL endlich ist. Auf diesem Satz beruht auch die Existenz des Minimalautomaten, der ja auch
Äquivalenzklassenautomat heisst.
10.2
10.2.1
Chomsky 3
Beschreiben die regulären Ausdrücke (a∗ a∗ ) und (a∗ |a∗ )∗ die selbe Sprache?
Beide Ausrücke beschreiben die Sprache, die durch den Ausdruck a∗ beschrieben wird.
10.2.2
Geben Sie einen endlichen Automaten für (a∗ |a∗ )∗ an.
Der Automat, der a∗ akzeptiert, sieht so aus:
a
z0
Der Automat A = (Q, Σ, δ, I, F ) ist definiert mit
Q
=
{z0 }
Σ = {a}
I = {z0 }
δ
F
10.2.3
= {(z0 , a, z0 )}
= {z0 }
Was sind reguläre Ausdrücke?
Reguläre Ausdrücke sind Formeln zur Beschreibung regulärer Sprachen. Sind sind induktiv definiert:
∅ ist ein regulärer Ausdruck
ist ein regulärer Ausdruck
jedes a ∈ Σ ist ein regulärer Ausdruck
sind α und β reguläre Ausdrücke, so ist auch αβ ein regulärer Ausdruck
sind α und β reguläre Ausdrücke, so ist auch α|β ein regulärer Ausdruck
ist α ein regulärer Ausdruck, so ist auch α∗ ein regulärer Ausdruck
10.2.4
Wie zeigt man, dass der Schnitt zweier regulärer Sprachen wieder eine reguläre Sprache ist?
Mit Hilfe der folgenden zwei Aussagen und des Gesetzes von De Morgan lässt sich die Abgeschlossenheit
unter Schnitt beweisen.
1. Reguläre Sprachen sind unter der Vereinigung abgeschlossen. Dies gilt, weil die regulären Ausrücke
genau die regulären Sprachen beschreiben und die Vereinigung eine der Operation bei regulären
Ausdrücken ist.
2. Reguläre Sprachen sind unter Komplementbildung abgeschlossen. Dies kann durch einen komplementären Automaten gezeigt werden. Vertauscht man bei einem Automaten A Endzustände mit
Nicht-Endzuständen, so erhält man einen Automaten A0 , der die Komplementärsprache erkennt.
132
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.2. Chomsky 3
Mit dem Gesetz von De Morgan ergibt sich für zwei Sprachen L1 und L2 :
L1 ∪ L 2 = L 1 ∩ L 2
10.2.5
Zeigen Sie, dass das Komplement bei regulären Sprachen abgeschlossen ist.
siehe 10.2.4
10.2.6
Welchen Typ hat die Sprache a3j+2 bi+1 , j, i ≥ 0? Geben Sie einen Automaten dazu an.
Da i und j nicht voneinander abhängig sind, handelt es sich um eine reguläre Sprache, ein entsprechender
Automat für i = j = 0 sieht so aus:
z0
10.2.7
a
z1
a
z2
b
z3
Was für Varianten von endlichen Automaten gibt es?
Ein endlicher Automat A = (Q, Σ, δ, I, F ) heißt:
1. Automat mit einem Startzustand wenn gilt |I| = 1.
2. alphabetisch, wenn gilt δ ⊆ Q × (Σ ∪ {}) × Q, d. h. jeder Übergang ist mein genau einem Zeichen
oder markiert
3. buchstabierend, wenn gilt δ ⊆ Q×Σ×Q, d. h. jeder Übergang ist mit genau einem Zeichen markiert,
ist nicht erlaubt
4. deterministisch (DEA), wenn er buchstabierend ist, genau einen Startzustand hat und für alle
p, q, r ∈ Q und alle a ∈ Σ mit (p, a, q) ∈ δ und (p, a, r) ∈ δ gilt q = r, d. h. von jedem Zustand gibt
es jeweils nur einen Übergang mit der Markierung a.
5. vollständig, wenn für jedes p ∈ Q und jedes a ∈ Σ ein q ∈ Q mit (p, a, q) ∈ δ existiert, d. h. von
jedem Zustand gibt es für jeden Buchstaben des Alphabets einen Übergang.
10.2.8
Sind reguläre Sprachen unter Homomorphismen abgeschlossen?
Ja. Der Beweis ergibt sich aus dem Beweis für die Substitution. Dieser Beweis läuft induktiv über
reguläre Ausdrücke und Arbeitet auf der syntaktischen Repräsentation der Sprache.
10.2.9
i Wie wandelt man einen endlichen Automaten in einen regulären Ausdruck um?
Man verwandelt den Automaten schrittweise in einen verallgemeinerten Automaten an dessen Kanten
reguläre Ausrücke stehen. Das mach man solang bis nur noch zwei Zustände, ein Startzustand und
ein Endzustand übrig bleiben. Auf der einzigen verbleibenden Transition steht der gesuchte reguläre
Ausdruck. Beispiel, Elimination des Zustandes qi :
ac*d
a
b
c
qi
d
bc*d
ac*e
e
f
bc*e|f
10.2.10 Pumping-Lemma erklären und beweisen.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
133
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
Sei L eine reguläre Sprache. Dann gibt es eine Zahl n, so dass sich alle Wörter x ∈ L mit |x| ≥ n
zerlegen lassen in x = uvw, so dass folgende Eigenschaften erfüllt sind:
1. |v| ≥ 1,
2. |uv| ≤ n,
3. für alle i = 0, 1, 2, . . . gilt: uv i w ∈ L
Mit Hilfe des Pumping Lemmas lässt sich zeigen, dass eine Sprache nicht regulär ist. Der Beweis läuft
über die Konstruktion eines Automaten:
Da L regulär ist, gibt es einen Automaten A, der L erkennt. Für die Zahl der Zustände Q wählt man
|Q| = n. Ein beliebiges Wort x hat die Länge ≥ n, daher durchläuft der Automat beim Abarbeiten
des Wortes |x| + 1 Zustände (wenn man den Startzustand mit zählt). Mit dem Schubfachprinzip kann
man schliessen, dass diese Zustände nicht alle verschieden sein können (|x| ≥ n), d. h. irgendwann muss
der Automat eine Schleife durchlaufen. Jetzt wählt man die Zerlegung x = uvw so, dass Zustand nach
dem Lesen von u und uv derselbe ist. Diese Zerlegung kann so gewählt werden, dass Bedingung 1 und
2 erfüllt werden. Da die Zustände die selben sind, erreicht der Automat beim Lesen des Wortes uw
denselben Endzustand wie beim Lesen von x = uvw. Das heisst uw = uv 0 w ∈ L. Dasselbe gilt für
uvvw = uv 2 w, uvvvw = uv 3 w, usw. Damit ist auch Bedingung 3 erfüllt.
10.2.11 Pumping-Lemma auf Sprache der Palindrome anwenden.
Man nimmt an, dass die Sprache der Palindrome regulär ist und führt das mit dem Pumping Lemma
zum Widerspruch. Man wählt ein Wort x wie folgt:
n
n
z }| { z }| {
x = aa . . . aa b aa . . . aa
Nun sei x = uvw die den Bedingungen 1 und 2 des Pumping Lemmas entspricht
. . aa} abaa
. . . aa}
x = aa
. . aa} |aa .{z
| {z
| .{z
u
Wegen |v| ≥ 1 müsste dann auch
v
w
≤n
n
z }| { z }| {
uw = aa . . . aa b aa . . . aa
ein Wort der Sprache sein. Dies ist jedoch kein Palindrom, da das Wort mehr a’s als b’s enthält. Also
kann die Sprache der Palindrome nicht regulär sein.
10.2.12 Pumping-Lemma auf ai bi anwenden.
Man nimmt an, dass L = {ai bi | i ≥ 0} regulär ist und führt das mit dem Pumping Lemma zum
Widerspruch. Nun wählt man das Pumping Lemma n und betrachtet genau das Wort an bn mit der
Länge 2n. Für die Zerlegung uvw ergibt sich:
1. v ist nicht leer (Bedingung 1)
2. uv und v können nur aus a’s bestehen (Bedingung 2)
3. wegen Bedingung 3 müsste dann aber auch das Wort uv 0 w = uw = an−|v| bn in der Sprache sein.
Diese widerspricht der Definition von L, daher ist L nicht regulär.
10.2.13 Was ist der Unterschied zwischen einem NEA und DEA?
siehe 10.2.7
10.2.14 Welche Form haben die Produktionen bei regulären Sprachen?
Für jede Produktion l → r muss gelten |l| ≤ |r|, l muss eine einzige Variable sein, r ist ein Terminal
oder ein Terminal gefolgt von einer Variablen.
134
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.2. Chomsky 3
10.2.15 Wie funktioniert die Umwandlung von einem nicht-deterministischen Automaten zu einem deterministischen Automaten?
Die Umwandlung von einem NFA zu einem DFA läuft in 4 Schritten ab
1. endlicher Automat −→ Automat mit einem Startzustand
Man fügt einen neuen Startzustand q0 hinzu. Von diesem Zustand gibt es einen -Übergang zu allen
alten Startzuständen.
2. Automat mit einem Startzustand −→ alphabetischer Automat mit einem Startzustand
Ein Übergang mit einem Wort w = a1 a2 . . . an wird in mehrere Übergänge, die jeweils nur mit
einem Zeichen markiert sind, aufgeteilt. Dazu müssen n − 1 Zwischenzustände eingeführt werden.
3. alphabetischer Automat mit einem Startzustand −→ buchstabierender Automat mit einem Startzustand (-Elimination)
Beim Entfernen der -Übergänge muss sicher gestellt werden, dass die akzeptierte Sprache sich nicht
ändert. Die -Elimination gliedert sich in drei Teilschritte.
a) Für jede Kette von -Übergängen von p nach r gefolgt von einem a-Übergang von r nach q fügt
man einen a-Übergang von p nach r hinzu.
b) Falls von p eine Kette von -Übergängen zu einem Endzustand führt, wird p auch zum Endzustand.
c) Jetzt kann man die -Übergängen löschen.
4. buchstabierender Automat mit einem Startzustand −→ deterministischer endlicher Automat (Potenzautomatenkonstruktion)
Die Idee ist, alle Wege im buchstabierenden Automaten gleichzeitig zu Verfolgen und sich die
Zustände zu merken, in denen sich der Automat befinden könnte. Dazu verwendet man die Potenzautomatenkonstruktion. Für einen buchstabierenden Automaten A = (Q, Σ, δ, q0 , F ) definiert
man einen Automaten A0 = (P(Q), Σ, δ 0 , {q0 }, F 0 ), wobei P(Q) die Potenzmenge von Q ist. Die
Übergangsrelation δ 0 definiert man so: (P, a, R) ∈ δ 0 gdw. R = {r ∈ Q | ∃p ∈ P : (p, a, r) ∈ δ}
wobei P und R Teilmengen von Q also Element von P(Q) bzw. Zustände des Potenzautomaten
sind. Die Menge der Endzustände ist definiert durch F 0 = {P ⊆ Q | P ∩ F 6= ∅}, d. h. diejenigen
Teilmengen von Q, die mindestens einen Endzustand enthalten.
Der entstandene Automat A0 ist meist nicht minimal, er kann aber mit dem Myhill-Verfahren minimalisiert werden (10.2.18).
10.2.16 Sind reguläre Sprachen gleich den linearen Sprachen?
Eine Grammatik heisst rechtslinear wenn alle Produktionen die Form
A → wB
oder
A→w
haben. Sie heisst linkslinear wenn alle Produktionen die Form
A → Bw
oder
A→w
haben.
Eine Sprache L ist genau dann regulär, wenn es eine rechtslineare oder linkslineare Grammatik G mit
L = L(G) gibt.
Um dies zu Beweisen, kann man zeigen, dass es für jede lineare Grammatik einen endlichen Automaten
gibt, der diese Sprache erkennt. In der anderen Richtung muss man zeigen, dass für jede reguläre
Sprache einen lineare Grammatik gibt.
10.2.17 Wie zeigen Sie die Äquivalenz zweier regulärer Sprachen?
Von beiden Sprachen den Minimalautomaten bauen. Diese beiden Automaten müssen bis auf Isomorphie gleich sein, wenn die Sprachen äquivalent sind.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
135
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
10.2.18 Algorithmus zur Minimalisierung von DEAs.
Zuerst kann man Zustände, die vom Startzustand aus nicht erreichbar sind, streichen. Dann bestimmt
man Paare von äquivalenten Zuständen. Dazu bestimmt man iterativ alle nicht-äquivalenten Zustände,
in dem man die folgenden Regeln anwendet, bis sich keine Änderungen mehr ergeben.
Wenn von zwei Zuständen einer ein Endzustand ist und der andere nicht, so sind die Zustände nicht
äquivalent
p∈F ∧q ∈
/F
⇒
p 6≡ q
Wenn von zwei Zuständen ein a-Übergang zu zwei nicht-äquivalenten Zuständen existiert, dann
sind auch die beiden Zustände nicht äquivalent.
(p, a, r) ∈ δ ∧ (q, a, r 0 ) ∈ δ ∧ r 6≡ r 0
⇒
p 6≡ q
Etwas detaillierter lässt sich der Algorithmus so beschreiben:
1. Stelle eine Tabelle aller Zustandspaare {q, q 0 } mit q 6= q 0 von A auf.
2. Markiere alle Paare {q, q 0 } mit q ∈ F und q 0 ∈
/ F (oder umgekehrt).
3. Für jedes noch unmarkierte Paar {q, q 0 } und jedes a ∈ Σ teste, ob
{δ(q, a), δ(q 0 , a)}
bereits markiert ist. Falls ja, wird auch {q, q 0 } markiert.
4. Der letzte Schritt wird so lange wiederholt, bis sich keine Änderungen mehr ergeben.
5. Alle jetzt noch unmarkierten Paar sind äquivalent und können daher verschmolzen werden.
10.3
10.3.1
Chomsky 2
Welchen Typ hat die Sprache ai+1 b3i , i ≥ 0? Geben Sie einen Automaten dazu an.
Diese Sprache ist kontextfrei, da die Anzahl der b’s von der der a’s abhängt. Der Kellerautomat liest
erstmal ein a ohne den Keller zu verändern, dann pusht er für jedes gelesene a drei Zeichen. Beim Lesen
eines b’s wird jeweils eins dieser Zeichen vom Keller geholt. Akzeptanz durch leeren Keller.
10.3.2
Was ist eine kontextfreie Sprache?
Eine kontextfreie Sprache ist vom Chomsky Typ 2, wird von einem Kellerautomaten akzeptiert und
von einer kontextfreien Grammatik erzeugt.
10.3.3
Welche Automaten erkennen kontextfreie Sprachen?
Kellerautomaten.
10.3.4
Erkennt ein deterministischer Kellerautomat kontextfreie Sprachen?
Ein deterministischer Kellerautomat erkennt nur deterministisch-kontextfreie Sprachen.
10.3.5
Welche Normalformen für kontextfreie Sprachen gibt es und für was sind sie gut?
Es gibt die
Chomsky Normalform. Hier haben alle Produktionen die Form A → BC oder A → a. Die Chomsky
Normalform wird für die Anwendung des CYK-Algorithmus’ gebraucht.
Greibach Normalform. Alle Produktionen haben die Form A → aB1 B2 . . . Bn . Sie wird zur Konstruktion von Kellerautomaten benötigt.
136
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.3. Chomsky 2
10.3.6
Erklären und beweisen Sie das Pumping-Lemma für kontextfreie Sprachen.
Sei L eine kontextfreie Sprache. Dann gibt es eine Zahl n ∈ N, so dass sich alle Wörter z ∈ L mit
|z| ≥ n zerlegen lassen in z = uvwxy mit folgenden Eigenschaften:
1. |vx| ≥ 1
2. |vwx| ≤ n
3. für alle i ≥ 0 gilt: uv i wxi y ∈ L
Beweisidee: Wenn eine Grammatik eine Sprache L mit unendlich vielen Wörtern erzeugt, dann muss es
Wörter geben in deren Ableitungsbaum auf einem Pfad dieselbe Variable mehrfach vorkommt (Schubfachprinzip).
S
(1)
S
A
A
u
v
w
A
(1)
A
(2)
(2)
A
x
y
u
v
v
w
x
x
y
Die Abbildung zeigt einen solchen Ableitungsbaum für das Wort uvwxy und uvvwxxy. Man kann
den bei Knoten (1) beginnenden Teilbaum so wählen, dass auf keinem Pfad dieses Teilbaums zwei
gleiche Variablen vorkommen. Jetzt kann man das Teilstück des Baumes zwischen (1) und (2) beliebig
oft wiederholen und erhält damit Ableitungsbäume für die Wörter uv i wxi y. Da in jedem bei (1)
beginnenden Teilbaum auf keinem Pfad Variablen doppelt vorkommen gilt |vwx| ≤ n für ein geeignetes
n. Man kann davon ausgehen, dass es in der Grammatik keine -Produktionen gibt, daher gilt auch
|vx| ≥ 1.
10.3.7
Zeigen Sie, dass L = {am bm cm } nicht kontextfrei ist.
Man nimmt an, dass L kontextfrei ist und für das mit dem Pumping Lemma zum Widerspruch. Man
wählt das Wort z = an bn cn . Dann hat z die Länge 3n ≥ n. Wegen Bedingung 2 können v und x
entweder nur aus a’s und b’s oder aus b’s und c’s bestehen. vx muss wegen Bedingung 1 mindestens ein
Zeichen enthalten. Dann kann aber uv 2 wx2 y nicht in L sein, da es entweder mehr a’s als c’s oder mehr
c’s als a’s enthält.
10.3.8
Was sind kontextfreie Grammatiken?
Bei kontextfreie Grammatiken gilt für jede Produktion l → r, |l| ≤ |r und das l eine einzige Variable
sein muss.
10.3.9
In welcher Klasse liegt die Sprache der Palindrome?
Palindrom sind vom Chomsky-Typ 2. Sie sind nicht deterministisch-kontextfrei.
10.3.10 Wie funktioniert der Kellerautomat für Palindrome?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
137
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
Der Kellerautomat für Palindrome muss die Mitte des Wortes erraten. Der Kellerautomat könnte so
aussehen.
Q = {q0 , q1 }
Γ = Σ ∪ {c}
Z0 = c
F =∅
δ = {((q0 , x, y), (q0 , xy)) | x ∈ Σ, y ∈ Γ} ∪
{((q0 , , y), (q1 , y) | y ∈ Γ} ∪
nächstes Eingabezeichen pushen (1)
Entscheidung Mitte (gerade länge) (2)
{((q0 , x, y), (q1 , y)) | x ∈ Σ, y ∈ Γ} ∪
{((q1 , x, x), (q1 , )) | x ∈ Σ} ∪
{((q1 , , c), (q1 , ))}
Entscheidung Mitte (ungerade länge) (3)
Keller mit Eingabe vergleichen (4)
Startsymbol vom Keller löschen (5)
Die Menge der Endzustände F ist leer, da der Automat durch den leeren Keller akzeptiert.
10.3.11 Was sind nutzlose Variablen?
Eine Variable heisst nützlich wenn sie in mindestens einer Ableitung eines Wortes vorkommt. Wenn
eine Variable nicht nützlich ist, ist sie nutzlos. Eine nützliche Variable ist produktiv und erreichbar
(aber nicht umgekehrt).
Eine Variable A heisst produktiv, wenn aus ihr mindestens ein Wort abgeleitet werden kann.
Eine Variable A heisst erreichbar, wenn sie in mindestens einer Satzform vorkommt.
10.3.12 Was ist eine nullierbare Variable?
Eine Variable A einer Grammatik G heisst nullierbar, wenn gilt A ⇒∗G .
10.3.13 Wie erstellt man eine Grammatik, die keine -Produktion, keine Kettenproduktion und keine nutzlosen
Variablen enthält?
1. Elimination von -Produktion
Wenn die Grammatik eine Produktion enthält mit der Form A → A1 . . . An bei der für ein i ∈
{1, . . . n} die Variable Ai nullierbar ist, dann wird die Produktion durch A → A1 . . . Ai−1 Ai+1
ersetzt (Ai bleibt also weg). Die wird solange angewandt, bis es keine solchen Produktionen mehr
gibt. Produktionen der Form A → werden gelöscht. Diese Grammatik kann keine Sprachen
erzeugen, die enthalten.
2. Elimination von Kettenproduktionen
Jede Sequenz von Kettenproduktionen A ⇒∗G B gefolgt von eine Nicht-Kettenproduktion B → α
wird ersetzt durch eine Produktion A → α.
3. Entfernen von nutzlosen Variablen (dieser Schritt ist bei manchen Definitionen der Chomsky Normalform nicht gefordert)
Bei den beiden folgenden Schritten kommt es auf die Reihenfolge an.
a) Alle nicht-produktiven Variablen und die Produktionen in denen sie vorkommen können entfernt
werden, ohne dass die Sprache sich ändert.
b) Alle nicht-erreichbaren Variablen und die Produktionen in denen sie vorkommen können entfernt
werden, ohne dass die Sprache sich ändert.
10.3.14 Erklären Sie die Chomsky-Normalform und wie man sie erstellt.
Eine Grammatik ist in Chomsky-Normalform, wenn alle Produktionen die Form
A → BC
oder
A→a
haben. Um eine Grammatik vom Typ 2, die keine -Produktion, keine Kettenproduktion und keine
nutzlosen Variablen enthält, in Chomsky-Normalform zu überführen sind folgende Schritte notwendig.
138
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.3. Chomsky 2
1. Für jedes Terminal a wir eine neue Variable Ba und eine Produktion Ba → a eingefügt. Ausserdem
ersetzt man in jeder Produktion der Form A → α mit |α| ≥ 2 jedes Zeichen a in α durch die
Variable Ba
2. Jetzt ersetzt man jede Produktion der Form A → A1 . . . An mit n > 2 durch diese n−1 Produktionen
A
→
A 1 C1
C1
→
A 2 C2
C2
→
A 3 C3
..
.
Cn−2
→
An−1 An
wobei C1 , . . . , Cn−2 neue Variablen sind. Bei einer Grammatik in Chomsky Normalform hat die
Ableitung eines Wortes der Länge n genau 2n − 1 Schritte.
10.3.15 Sind kontextfreie Sprachen unter Schnitt abgeschlossen?
Nein. Beweis durch Gegenbeispiel. Die Sprachen L1 = {ai bj cj | i, j ≥ 0} und L2 = {ai bi cj | i, j ≥ 0}
sind beide Kontextfrei. Der Schnitt der Sprachen
L = L1 ∪ L2 = {ai bi ci | i ≥ 0}
ist aber nicht kontextfrei.
10.3.16 Wenn ich Ihnen einen Automaten auf den Tisch stelle, können Sie dann sagen, welchen Typ von Sprachen
er erkennt?
Es muss sich um einen EA handeln, da der unendliche Keller des Kellerautomaten nicht auf den Tisch
passen würde.
10.3.17 Wie sind Kellerautomaten definiert?
Ein Kellerautomat über einem Alphabet Σ besteht aus
einer endlichen Menge von Zuständen Q
einem Startzustand z0 ∈ Q
einem Kelleralphabet Γ
einem Anfangssymbol Z0 ∈ Γ
einem Menge von Endzuständen F
einer Übergangsrelation δ ⊆ (Q × (Σ ∪ {}) × Γ) × (Q × Γ∗ )
10.3.18 Wie definiert man einen Zustandsübergang?
Zustandsübergang kann als Funktion oder Relation definiert werden. Definition mit Relation siehe
10.3.17.
10.3.19 Welchen Arten von Akzeptanz gibt es bei Kellerautomaten. Zeigen Sie die Äquivalenz dieser Arten.
Es gibt Akzeptanz über Endzustände und Akzeptanz mit leerem Keller.
Ein Automat A der durch leeren Keller akzeptiert, kann wie folgt in einen Automaten A 0 , der durch
Endzustand akzeptiert umgewandelt werden.
1. Hinzufügen eines neuen Kellersymbols X0 ∈
/Γ
2. Hinzufügen eines Endzustandes Qf ∈
/Q
3. Automaten so modifizieren, dass er im ersten Schritt das Kellersymbol Z 0 durch Z0 X0 ersetzt
4. Automat A0 simuliert dann den Automaten A
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
139
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
5. Wenn die Berechnung mit leerem eigentlich beendet wäre, liegt auf dem Keller noch das Symbol
X0 . Deshalb werden Übergänge hinzugefügt, so dass der Automat X0 aus dem Keller löscht und in
den Endzustand Qf übergeht.
Ein Automat A der durch Endzustände akzeptiert, kann wie folgt in einen Automaten A0 , der durch
leeren Keller akzeptiert umgewandelt werden.
1. Automat A0 simuliert Automat A
2. Wenn A0 einen Endzustand erreicht, kann er sich nicht-deterministisch dafür entscheiden, den Keller
komplett zu löschen und damit Akzeptanz über leeren Keller zu erreichen.
Problem: Wenn A0 den leeren Keller erreicht, A sich aber nicht in einem Endzustand befindet, wird A 0
das Wort akzeptieren, obwohl A es nicht tut.
Lösung: Im ersten Schritt erzeugt A0 aus dem Startsymbol Z0 den Kellerinhalt Z0 X0 mit einem Kellersymbol X0 ∈
/ Γ. Damit kann der Keller garantiert nie leer werden. Der Keller wird nur leer, wenn
sich der Automat in einem Endzustand nicht-deterministisch für das komplette löschen des Kellers
entscheidet.
10.3.20 Geben Sie die Grammatik für Palindrome an.
Für das Alphabet Σ = {0, 1}.
S
S
S
S
S
S
→
→
0S0
1S1
→
→
00
11
→
→
0
1
10.3.21 Was ist eine linksrekursive Grammatik?
Eine linksrekursive Grammatik enthält Produktionen bei denen die erste Variabel auf der rechten Seiten
gleich der Variablen auf der linken Seite ist. Zum Beispiel
A → AB
Linksrekursive Grammatiken sind ungeeignet für die Verarbeitung mit Top-Down-Parsern, da diese
dabei in Endlosschleifen geraten können. Für die Elimination von Linksrekursionen, siehe 2.3.6.
10.3.22 Was ist eine mehrdeutige Grammatik?
Bei einer mehrdeutigen Grammatik gibt es für mindestens ein Wort verschiedene Ableitungsbäume.
10.3.23 Erklären Sie die Begriffe LL(k) und LR(k).
siehe 2.3.3.
i Welche Komplexität hat das Wortproblem?
10.3.24 Das Wortproblem kann mit dem CYK-Algorithmus in O(n3 ) gelöst werden.
10.3.25 Wie kann man eine Grammatik -frei machen?
siehe 10.3.13
140
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.4. Chomsky 1
10.4
10.4.1
Chomsky 1
i Ist das Wortproblem für kontextsensitive Sprachen entscheidbar?
Ja, aber N P -hart.
10.4.2
i Geben Sie einen Algorithmus für das Wortproblem an.
Man startet mit dem Startsymbol und leitet so oft ab, bis man das Wort gefunden hat oder nicht mehr
ableiten kann.
n
wie folgt definiert.
Formell: Für m, n ∈ N werden die Mengen Tm
n
Tm
= {w ∈ (V ∪ Σ)∗ | |w| ≤ n und w lässt sich aus S in höchstens m Schritten ableiten}
n
Die Mengen Tm
, n ≥ 1 lassen sich induktiv über m definieren.
T0n
n
Tm+1
Abln (X)
=
{S}
n
= Abln (Tm
), wobei
= X ∪ {w ∈ (V ∪ Σ)∗ | |w| ≤ n und w 0 ⇒ w für ein w0 ∈ X}
Abln (X) bildet also aus einer Menge von Wörtern (Satzformen) eine neue Menge, in dem sie X um alle
Wörter, die in einem Schritt aus allen Wörter aus X herleitbar sind, erweitert. Aufgenommen werden
nur Wörter, deren Länge ≤ n ist.
Da es nur endlich viele Wörter der Länge n gibt, ist
[
n
Tm
m≥0
für jedes n eine endliche Menge. Deshalb kann man folgenden Algorithmus angeben, der das Wortproblem für Typ 3, 2 und 1 Sprachen löst, da diese die Wortlängenmonotonie erfüllen. Als Eingabe erhält
der Algorithmus ein Wort und eine Grammatik.
Wortproblem(G, x)
1 n ← |x|
2 T ← {S}
3 do{
4
T1 ← T
5
T ← Abln (T1 )
6 } until (x ∈ T ) or (T = T1 )
7 if (x ∈ T ) return Ja
8 else return Nein
Dieser Algorithmus terminiert immer, hat aber exponentielle Laufzeit.
10.4.3
i Welche Komplexität hat dieser Algorithmus?
Ist N P -hart und daher Komplexität O(2n )
10.4.4
Was ist Wortlängenmonotonie?
Auch bei kontextsensitiven Sprachen können Worte in jedem Ableitungsschritt nur länger werden oder
gleich lang bleiben. Das ist eine grundlegende Voraussetzung für die Entscheidbarkeit des Wortproblems.
10.4.5
Welche Automaten erkennen kontextsensitive Sprachen?
Linear beschränkte Turingmaschinen.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
141
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
10.4.6
Was ist das für eine Sprache {ww|w ∈ {0, 1}∗ }?
Es handelt sich um eine kontextsensitive Sprache. Diese Sprache beschreibt das aus dem Compilerbau
bekannte Problem, das eine Variable zuerst deklariert werden muss, bevor sie benutzt wird.
10.4.7
Welchen Typ hat die Sprache ak bm ak bm , k ∈ N, m ≥ 0?
Die Sprache ist kontextsensitiv. Sie entspricht dem Problem bei der Übersetzung eines Programmes
festzustellen, ob die Anzahl der Parameter beim Methodenaufruf gleich der Anzahl der Parameter bei
der Methodendeklaration ist.
10.5
10.5.1
Berechenbarkeit
Warum ist die Ackermannfunktion nicht primitiv rekursiv?
Informell: Man kann zeigen, dass man zur Berechnung von a(n+1, n+1) n verschachtelte For-Schleifen
braucht. Da dies für beliebige n gilt, gibt es keine Obergrenze für die Anzahl der For-Schleifen.
10.5.2
i Was ist der Satz von Rice und was bedeutet er?
Jede nicht-triviale Eigenschaft P ist unentscheidbar, d. h. die Sprache
LP = {hM i | M ist eine Turing-Maschine mit P (L(M ))}
ist nicht entscheidbar. Eine Eigenschaft von Sprachen ist eine Teilmenge P von aufzählbaren Sprachen.
Man schreibt P (L) wenn L die Eigenschaft erfüllt, d.ḣ. L ∈ P . Man schreibt ¬P (L) wenn L sie nicht
erfüllt. Eine Eigenschaft heisst nicht-trivial wenn es wenigstens eine aufzählbare Sprache mit L mit
P (L) und wenigstens eine aufzählbare Sprache L0 mit ¬P (L0 ) gibt.
Beispiel : Es ist nicht entscheidbar, ob eine Turing-Maschine nur endlich viele Wörter akzeptiert (d. h.
ob die Sprache endlich ist).
Die Eigenschaft P ist definiert durch P (L) = {L | |L| < ω}. Die Eigenschaft ist nicht trivial, da ¬P (Σ ∗ )
und P (∅).
Es ist nicht entscheidbar, ob die akzeptierte Sprache regulär ist. P (L) = {L | L ist regulär}. Eigenschaft
ist nicht-trivial: ¬P (an bn ) und P (∅)
10.5.3
i Erklären Sie den Begriff Aufzählbarkeit.
Der Begriff Aufzählbarkeit ist mit dem der Abzählbarkeit eng verwandt: Eine unendliche Menge M ist
aufzählbar wenn es eine surjektive, berechenbare Abbildung von N nach M gibt:
M = {f (1), f (2), f (3), . . .}
Die Abbildung muss auf jeden Fall berechenbar sein, hier liegt der Unterschied zur Abzählbarkeit. Wenn
diese Abbildung berechenbar ist, so kann auch jedes Element der Menge M tatsächlich erzeugt werden.
10.5.4
Was heisst rekursiv aufzählbar ?
Die Begriffe aufzählbar und rekursiv aufzählbar bedeuten im deutschen dasselbe.
10.5.5
Zeigen sie, dass eine rekursive aufzählbare Sprache semi-entscheidbar ist.
Satz: Eine Sprache ist rekursiv aufzählbar genau dann, wenn sie semi-entscheidbar ist.
Beweis: Von links nach rechts: Wenn die Sprache L mit der Funktion f rekursiv aufzählbar ist, dann
muss man nur der Reihe nach i = 0, 1, 2 . . . in f einsetzen und testen ob f (n) = x ist.
142
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.5. Berechenbarkeit
Von rechts nach links: Die Annahme ist, das die Sprache L semi-entscheidbar ist. Man sucht nach einer
Funktion f deren Wertebereich L ist, die also alle Elemente von A aufzählt.
Wenn L semi-entscheidbar ist, dann gibt es auch einen Algorithmus M , der diese Semi-Entscheidung
berechnet. Der Algorithmus bekommt ein Wort x der Sprache L als Eingabe und antwortet nach einer
endlichen Anzahl an Schritt mit ja oder er antwortet gar nicht. Mit Hilfe dieses Algorithmus kann
der in der Abbildung dargestellte Automat die Sprache aufzählen, in dem er mit natürlichen Zahlen
gefüttert wird (Automat nicht im Sinne von endlicher Automat).
n
C1
(x',y')
M'
x'
C2
x
M
ja
x
y'
K
a
{...}
M ist der bereits beschriebene Semi-Entscheidungs-Algorithmus. Er ist der zentrale Bestandteil des
Automaten M 0 . M 0 erweitert M um eine Kontrolleinheit K, die M nach einer bestimmten Anzahl von
Schritten abbrechen kann. Des weiteren wählt man a als ein Wort, das in der Sprache L liegt. Jetzt
erhält der Automat ein 2-Tupel (x0 , y 0 ) wobei x0 ∈ N und y 0 ∈ N als Eingabe. y 0 wird der Kontrolleinheit
K zugeführt, diese kann M nach y 0 Schritten abbrechen.
Der andere Teil des Tupels x0 ist ebenfalls eine natürliche Zahl, die aber ein Wort codiert. Entscheidend
dabei ist, dass jedes Wort als natürliche Zahl codiert werden kann. Dieses codierte Wort x0 wird von
Codierer C2 in das Wort x übersetzt. Der Algorithmus wird nun auf das Wort x angesetzt und gibt,
falls x ein Wort der Sprache ist, ja aus. Falls M ja ausgibt, gibt M 0 das Wort x aus. Da nicht
entscheidbar ist, ob der Algorithmus jemals anhält, bricht ihn die Kontrolleinheit nach y 0 Schritten ab.
In diesem Falle gibt M 0 das Wort a aus.
Man sieht, dass M 0 auf jeden Fall stoppt und immer ein Wort der Sprache ausgibt. M 0 erzeugt alle
Wörter der Sprach, wenn die Eingabe-Tupel alle Wörter enthalten und für jedes Wort, die Anzahl
der Schritte y 0 gross genug ist. Um dies sicher zustellen muss man den Algorithmus einfach mit allen
Wörter, die es gibt füttern und für jedes Wort alle möglichen Anzahlen an Schritten zulassen. Da heisst,
M 0 erzeugt alle Wörter, wenn er als Eingabe alle Tupel (N × N) erhält.
Genau dafür ist der Codierer C1 zuständig. Dieser erhält als Eingabe eine natürliche Zahl und erzeugt
als Ausgabe ein 2-Tupel mit natürlichen Zahlen. Es gibt berechenbare Funktionen, die solche Tupel
erzeugen ([Schöning, 1997, S. 111]), da (N × N) aufzählbar ist.
Der ganze Automat erzeugt nun alle Wörter der Sprache L, wenn er alle natürlichen Zahlen als Eingabe
enthält. Er berechnet also eine Funktion mit Definitionsbereich N und Wertebereich L.
10.5.6
Erklären Sie den Begriff Berechenbarkeit.
Laut der Churchschen These stimmt die durch die formale Definition der Turing-Berechenbarkeit erfasste Klasse von Funktionen genau mit der Klasse der im intuitiven Sinne berechenbaren Funktionen
überein.
Informell: Berechenbar ist, was man z. B. in Java programmieren kann.
10.5.7
Wie sind die primitiv rekursiven Funktionen definiert?
Die primitiv rekursiven Funktionen sind induktiv definiert:
1. Alle konstanten Funktionen sind primitiv rekursiv.
2. Alle identischen Abbildungen (Projektionen) sind primitiv rekursiv.
3. Die Nachfolgerfunktion s(n) = n + 1 auf den natürlichen Zahlen ist primitiv rekursiv.
4. Jede Funktion die durch Einsetzung (Komposition) von primitiv rekursiven Funktionen entsteht,
ist selbst primitiv rekursiv.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
143
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
5. Jede Funktion, die durch sog. primitive Rekursion aus primitiv rekursiven Funktionen entsteht, ist
primitiv rekursiv. Primitive Rekursion bedeutet, dass die Definition von f (n + 1, . . .) zurückgeführt
wird auf f (n, . . .). Formal muss f ein Gleichungssystem der folgenden Form erfüllen:
f (0, . . .) = g(. . .)
f (n + 1, . . .) = h(f (n, . . .), . . .)
wobei g, h selbst primitiv rekursive Funktionen sind.
10.5.8
Wie ist der µ-Operator definiert?
Durch Anwendung des µ-Operators wird aus einer n + 1-stelligen Funktion g eine n-stellige Funktion
µg.
min{k ∈ N | g(x, k) = 0 ∧ (g(x, j) ist definiert für alle j ≤ k)}
(µg)(x) =
undefiniert, falls min nicht existiert
µg(x) bezeichnet also den kleinsten Index k, für den g(x, k) = 0 gilt und für den für alle j ≤ k der Wert
g(x, j) definiert ist.
10.5.9
Wie unterscheiden sich die primitiv rekursiven von den µ-rekursiven Funktionen?
Die Berechbarkeitsmächtigkeit der primitiv rekursiven Funktion entspricht der Loop-Berechenbarkeit.
Die Berechbarkeitsmächtigkeit der µ-rekursiven Funktionen entspricht der While- bzw. Turing-Berechenbarkeit.
10.5.10 Wie geht die Umwandlung einer nicht-deterministischen Turingmaschine in eine Deterministische?
Dazu muss erstmal die Idee der beschränkten Simulation beschrieben werden. Ein beschränkter Simulator Sim(M ) einer TM M erweitert M um einen Zähler der mit n initialisiert wird. Sim(M ) erhält
als Eingabewort w#n wobei w das Eingabewort und n ein Wort aus n Strichen ist. Bei jedem Abarbeitungsschritt wird der Zähler um 1 decrementiert (ein Strich gelöscht). Ist der Zähler bei 0 bevor das
Wort w erkannt wurde, akzeptiert die Maschine nicht.
Diese Idee kann nun erweitert werden um eine DTM zu bauen. Gegeben sei folgende nicht-deterministische
Turing-Maschine M = (Q, Σ, Γ, δ, q0 , B, F ). Für einen Zustand q ∈ Q und ein gelesenes Zeichen a definiert man A(q,a) = {(p, b, m) | ((q, a), (p, b, m) ∈ δ} als die Menge der möglichen Übergänge nach q bei
gelesenem Eingabezeichen a. Man nennt A(q,a) die Menge der Alternative. Die maximale Anzahl k von
Alternativen der Turingmaschine ist k = max{|A(q,a) | | q ∈ Q, a ∈ Γ}
Nun kann man jeder Alternative aus A(q,a) eindeutig eine Nummer aus {1, 2, . . . , k} zuordnen. Jetzt sei
π = k1 k2 . . . kn mit ki = {1, 2, . . . , k}. Sei Sim(M ) eine Turingmaschine, die die Eingabe w#π erhält,
wobei w ∈ Σ∗ . Sim(M ) simuliert die Turingmaschine M auf der Eingabe w für |π| Schritte; ki gibt
in jedem Simulationsschritt an, welche Alternative der TM M die TM Sim(M ) wählen soll. Wenn die
Wahl einer alternative nicht möglich ist, wird die Simulation erfolglos abgebrochen.
Diese Maschine ist deterministisch, da jede Alternativenwahl vorgeben ist und stoppt nach |π| Schritten.
Nun kann man aus Sim(M ) eine Maschine M 0 bauen, die für die Eingabe w systematisch alle Paare
w#π erzeugt und dann Sim(M ) mit Eingabe w#π startet. Wenn Sim(M ) für ein π die Eingabe w#π
akzeptiert, dann akzeptiert M 0 die Eingabe w. Es gilt L(M ) = L(M 0 ). Denn es gilt w ∈ L(M 0 ) gdw.
ein π ∈ {1, 2, . . . , k}∗ mit w#π von Sim(M ) akzeptiert wird gdw w ∈ L(M ) gilt.
10.5.11 Zeigen Sie die Unentscheidbarkeit des Wortproblems?
Definition des Wortproblems:
LW = {hM i#hwi | M ist eine Turing-Maschine und w ∈ L(M )}
wobei hM i und hwi geeignete Repräsentationen der Turing-Maschine bzw. eines Wortes sind. Die Frage
ist nun, ist diese Sprache entscheidbar, das heisst, gibt es eine Turing-Maschine, die genau diese Sprache
erkennt, also für jede Kombination Turing-Maschine–Sprache mit ja oder nein antworten kann.
144
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.5. Berechenbarkeit
Die Unentscheidbarkeit wird durch einen Widerspruchsbeweis gezeigt. Man nimmt an, dass es eine
deterministische Turing-Maschine W mit L(W ) = LW gibt, die für alle Eingaben hält, also das Wortproblem löst.
Aus dieser angenommenen Turing-Maschine W wird jetzt eine Turing-Maschine M , wie in der Abbildung
gezeigt, konstruiert.
ja
M
x
D
x#x
W
ja
nein
nein
Ein Wort x, das in die Turing-Maschine M gegeben wird, wird zuerst vom Duplizierer D verdoppelt
zum dem Wort x#x. Diese Wort wird nun in die Turing-Maschine W gegeben, die auf jedem Wort
hält. Zum Schluss wird das Ergebnis noch negiert. Nun gibt man der Turing-Maschine ihre eigene
Repräsentation als Eingabe, also x = hM i. M verhält sich dann wie folgt.
Auf jeden Fall hält M , da der Duplizierer D immer hält und die Maschine W laut der Widerspruchsannahme auch immer hält.
Wenn M mit ja antwortet, dann muss W auf der Eingabe hM i#hM i mit nein gehalten haben.
Gemäss der Widerspruchsannahme gilt dann hM i#hM i ∈
/ LW . Die Turing-Maschine W löst ja das
Wortproblem, das sie mit nein Antwortet ist also hM i kein Wort der Sprache L(M ), die durch
die Turing-Maschine M erkannt wird. Es gilt also hM i ∈
/ L(M ). Das heisst aber wiederum, dass
die Maschine M auf der Eingabe hM i nicht mit der Antwort ja hält.
Dieser Widerspruch zeigt, dass die Turing-Maschine M für die Eingabe hM i nicht mit der Antwort
ja halten kann.
Wenn M auf der Eingabe hM i mit der Antwort nein hält, dann muss W auf der Eingabe
hM i#hM i mit ja halten. Dann gilt laut der Widerspruchsannahme, dass hM i#hM i ∈ LW .
Aufgrund der Definition von LW gilt dann aber auch hM i ∈ L(M ). Was aber bedeutet, dass M
mit der Antwort ja hält.
Dieser Widerspruch zeigt, dass die Turing-Maschine M für die Eingabe hM i nicht mit der Antwort
nein halten kann.
Die Turing-Maschine M hält also für die Eingabe hM i weder mit ja noch mit nein . Da die Maschine aber per Konstruktion immer hält, liegt ein Widerspruch vor. Die einzige Annahme die getroffen
wurde, war, dass es eine Maschine W gibt, die das Wortproblem löst. Aufgrund des Widerspruchs kann
W nicht existieren und somit ist das Wortproblem nicht entscheidbar.
10.5.12 Beweisen Sie die Unentscheidbarkeit des Halteproblems.
Definition des Halteproblems:
LH = {hM i#hwi | M ist eine Turing-Maschine und hält bei der Eingabe w}
wobei hM i und hwi geeignete Repräsentationen der Turing-Maschine bzw. eines Wortes sind. Die Frage
ist nun, ist diese Sprache entscheidbar, das heisst, gibt es eine Turing-Maschine, die genau diese Sprache
erkennt, also für jede Kombination Turing-Maschine–Sprache mit ja oder nein antworten kann.
Man zeigt die Unentscheidbarkeit des Halteproblems indem man das Wortproblem auf das Halteproblem
reduziert. Man zeigt, also, dass man aus einer Maschine die das Halteproblem entscheidet, eine Maschine
bauen könnte, die das Wortproblem entscheidet. Da das Wortproblem nicht entscheidbar ist, kann es
ein solche Maschine nicht geben.
Eine deterministische Turing-Maschine M kann man so umbauen, dass sei ein Wort genau dann akzepf bezeichnet.
tiert, wenn sie auf dem Wort hält. Die umgebaute Maschine wird mit M
Die folgende Maschine entscheidet das Wortproblem.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
145
Kapitel 10. Automaten, Formale Sprachen und Berechenbarkeit
ja
〈M〉#〈w〉
〈M〉#〈w〉
U
ja
H
nein
nein
Sie wird mit einer Instanz des Wortproblems gefüttert. Die Umbauer-Maschine U baut die Maschine M
f um. Diese Maschine akzeptiert w wenn sie auf ihm hält. Jetzt wird eine Beschreiin eine Maschine M
bung der umgebauten Maschine und das Wort in die Maschine H eingeführt. H ist die hypothetische
f auf w hält und antwortet immer.
Maschine, die das Halteproblem löst. Sie testet nun ob, M
Wie man sieht, würde dies Maschine das Wortproblem lösen. Da das Wortproblem aber bewiesenermassen unentscheidbar ist, kann die Maschine H nicht existieren und somit das Halteproblem auch
nicht entscheidbar.
i Beweisen Sie die das Halteproblem. (2. Variante)
10.5.13 Der Beweis läuft in zwei Schritten, zuerst beweist man das spezielle Halteproblem und reduziert es dann
auf das Halteproblem.
Spezielles Halteproblem: Unter dem speziellen Halteproblem versteht man die Sprache
K = {w ∈ {0, 1}∗ | Mw angesetzt auf w hält}
Diese Sprache ist nicht entscheidbar.
Beweis: Man nimmt an, dass K entscheidbar ist und führt diese Annahme zum Widerspruch. Falls
K entscheidbar ist, dann lässt sich χK mit einer Turingmaschine M berechnen. Nun baut man diese
Turing-Maschine M um in eine Turingmaschine um in eine Turingmaschine M 0 , die wie folgt definiert
ist.
M'
start
M
=0?
nein
ja
stop
Die Maschine M 0 stoppt wenn M 0 ausgibt, ansonsten gerät M 0 in eine Endlosschleife. Jetzt betrachtet
man ein Codewort w 0 der Maschine M 0 und kommt zu folgenden Schlussfolgerungen:
M 0 angesetzt auf w 0 hält
M 0 angesetzt auf w 0 hält
⇔
⇔
⇔
⇔
⇔
M angesetzt auf w 0 gibt 0 aus
χK (w0 ) = 0
w0 ∈
/K
Mw0 angesetzt auf w 0 hält nicht
M 0 angesetzt auf w 0 hält nicht
Der Widerspruch zeigt, dass die Annahme falsch war, K ist nicht entscheidbar.
Allgemeines Halteproblem: Unter dem allgemeinen Halteproblem versteht man die Sprache
H = {w#x| Mw angesetzt auf x hält}
Diese Sprache ist nicht entscheidbar.
Beweis: Wir wissen bereits, dass das spezielle Halteproblem nicht entscheidbar ist, dieses reduzieren wir
jetzt auf das allgemeine Halteproblem. D. h. wir zeigen, dass das spezielle Halteproblem eine Spezialfall
des allgemeinen Halteproblems ist, dann kann das allgemeine Halteproblem nicht entscheidbar sein.
Formal: Man zeigt, das K ≤ H. Dazu wählt man als Reduzierungsfunktion f (w) = w#w. Dann gilt:
w ∈ K ⇔ f (w) ∈ H.
146
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
10.5. Berechenbarkeit
i Was ist die Kleen’sche Normalform?
10.5.14 Ein Programm, dass nur aus einer einzigen While-Schleife besteht, ist in Kleen’scher Normalform.
10.5.15 Gibt es Funktionen, die Turing aber nicht Loop-berechenbar sind?
Ja. Z. B. die Ackermannfunktion.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
147
Kapitel 11
Logik
11.1
11.1.1
Allgemeines
Was bedeuteten Korrektheit und Vollständigkeit?
Die Aufgabe eines Kalküls ist es die Unerfüllbarkeit einer Formelmenge zu beweisen. Das Kalkül
muss vollständig und korrekt sein. Korrektheit bedeutet, dass keine erfüllbare Formel vermeintlich als
unerfüllbar erkannt wird. Vollständigkeit bedeutet, dass jede unerfüllbare Formel nachgewiesen werden
muss.
11.2
11.2.1
Aussagenlogik
Erklären Sie was gültige, erfüllbare und unerfüllbare Formeln sind.
Eine Formel F ist erfüllbar falls sie mindestens ein Modell A hat. Man schreibt A |= F . Eine Formel
F heisst gültig falls für jede zu F passende Belegung A gilt A |= F . Man nennt F eine Tautologie und
schreibt |= F . Eine Formel F heisst unerfüllbar falls es keine passende Belegung, die ein Modell ist,
gibt.
11.2.2
Wenn Sie einen Entscheidungsalgorithmus für die Erfüllbarkeit haben, wie können Sie zeigen, dass zwei
Formeln äquivalent sind?
Zeigen, dass A ↔ B eine Tautologie ist.
11.2.3
i Wie funktioniert die aussagenlogische Resolution?
Die Resolution ist ein aussagenlogisches Kalkül. Um Resolution anzuwenden muss die Formel in KNF
dargestellt werden. Vorteilhaft ist es dann die KNF-Formel als Mengen sog. Klauseln darzustellen.
Aus
F = (L1,1 ∨ . . . ∨ L1,n1 ) ∧ . . . ∧ (Lk,1 ∨ . . . ∨ Lk,nk )
wird
F = {{L1,1 , . . . , L1,n1 }, . . . , {Lk,1 , . . . , Lk,nk }}
wobei L Literale sind.
Wenn K1 , K2 und R Klauseln sind, dann heisst R Resolvent von K1 und K2 , falls ein Literal L gibt
mit L ∈ K1 und L ∈ K2 und R diese Form hat
R = (K1 − {L}) ∪ (L2 − {L})
Wenn F eine Klauselmenge ist, dann ist Res(F ) definiert als
Res(F ) = F ∪ {R | R ist Resolvent zweier Klauseln aus F }
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
149
Kapitel 11. Logik
Desweiteren ist
Res0 (F ) = F
und
Ausserdem ist
Res∗ (F ) =
Resn+1 (F ) = Res(Resn (F ))
[
Resn (F )
n≥0
Auf Unerfüllbarkeit wird mit dem Resolutionssatz getestet:
Resolutionssatz: Eine Klauselmenge F ist unerfüllbar genau dann, wenn 2 ∈ Res∗ (F ).
11.2.4
Was ist das Resolutionslemma?
Sei F eine Formel in KNF, dargestellt als Klauselmenge. Ferner sei R ein Resolvent zweier Klauseln
K1 und K2 . Dann sind F und F ∪ {R} äquivalent.
Beweis: Sei A eine zu F und damit auch zu F ∪ {R} passende Belegung. Wenn A |= F ∪ {R}, dann
gilt natürlich auch A |= F .
Umgekehrt wird angenommen, dass A |= F , dann gilt für alle Klauseln K ∈ F : A |= K. Der Resolvent
R hat die Form R = (K1 − {L}) ∪ (K2 − {L}) mit K1 , K2 ∈ F und L ∈ K1 , L ∈ K2 . Jetzt muss man
zwei Fälle unterscheiden.
1. Fall : A |= L
Da A |= L gilt sicherlich A 6|= L. Weiterhin gilt A |= K2 . Wenn A Modell für K2 ist, dann gilt auch
A |= (K2 −{L}, da das Literal, das aus der Klausel entfernt wird, ja eh nicht erfüllbar ist. Innerhalb
der Klausel sind alle Literale mit ∨ verbunden, deshalb ändert das entfernen einer 0 nichts. Der
Resolvent wird durch Vereinigung von (K1 − {L}) und (K2 − {L}) gebildet. Die einzelnen Literale
in R sind also wieder alle durch ∨ verbunden, da A |= K2 gilt, muss auch A |= R gelten.
2. Fall : A 6|= L
Da A |= k1 , gilt auch A |= (K1 − {L}) und somit A |= R.
Es gibt nur diesen beiden Fälle und für beide gilt, A |= R, also muss auch A |= F ∪ {R} gelten.
11.2.5
i Beweis für Korrektheit und Vollständigkeit der Resolution.
Resolutionssatz: Eine Klauselmenge F ist unerfüllbar genau dann, wenn 2 ∈ Res∗ (F ).
Korrektheit: Angenommen 2 ∈ Res∗ (F ). Die leere Klausel 2 kann nur durch Resolution zweier
Klauseln K1 und K2 mit K1 = {L} und K2 = {L} entstanden sein. Aus dem Resolutionslemma folgt:
F ≡ Res1 (F ) ≡ Res2 (F ) ≡ . . . ≡ Resn (F ) ≡ . . .
Da 2 in Res∗ (F ) enthalten ist (Annahme), ist für ein n ≥ 0, 2 ∈ Resn (F ), und damit auch K1 , K2 ∈
Resn (F ). Das es kein Modell gibt, das sowohl K1 als auch K2 erfüllt, ist Resn (F ) unerfüllbar. Da
Resn (F ) ≡ F , ist F unerfüllbar.
Vollständigkeit: Die Annahme ist nun, dass F unerfüllbar ist und man will zeigen, dass in diesem
Falle auch tatsächlich 2 ∈ Res∗ (F ) gilt. Der Beweis ist ein Induktionsbeweis über die Anzahl n der
atomaren Formeln in F . Aufgrund des Endlichkeitssatzes kann man sich auch wenn F eine unendliche
Formelmenge ist, auf eine endliche unerfüllbare Teilmenge von F beschränken.
Induktionsanfang: Falls n = 0, so kann F nur F = {2} sein und somit ist 2 ∈ Res ∗ (F ).
Induktionsschritt: Man wählt ein beliebiges aber festes n. Es wird angenommen, dass für jede unerfüllbare Klauselmenge G, die nur die atomaren Formeln A1 , A2 , . . . An enthält, gilt 2 ∈ Res∗ (F ).
Jetzt sei F eine Klauselmenge mit den atomaren Formeln A1 , A2 , . . . An+1 . Jetzt werden aus F zwei
neue Klauselmengen F1 und F0 wie folgt konstruiert.
F0 : Das Atom An+1 wird auf den Wert 0 fixiert. Dann entsteht F0 aus F indem jedes Vorkommen
von An+1 aus den Klausel gestrichen wird. Das geht da, A ∨ 0 = A. Ausserdem wird jede Klausel, die
¬An+1 enthält komplett gestrichen. Eine Klausel, die den Wert 1 enthält, hat insgesamt den Wert 1
und kann damit gestrichen werden.
150
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.2. Aussagenlogik
F1 : Das Atom An+1 wird auf den Wert 1 fixiert. Dann entsteht F1 aus F indem jedes Vorkommen von
¬An+1 aus den Klausel gestrichen wird. Das geht da, A ∨ 0 = A. Ausserdem wird jede Klausel, die
An+1 enthält komplett gestrichen. Eine Klausel, die den Wert 1 enthält, hat insgesamt den Wert 1 und
kann damit gestrichen werden.
Zu beachten ist, dass weder F0 noch F1 das Atom An+1 oder ¬An+1 enthalten. Im nächsten Schritt will
man zeigen, dass sowohl F0 wie F1 unerfüllbar sind. Dies wird mit einem Widerspruchsbeweis erreicht
(nur für F0 ausgeführt):
Angenommen es gibt eine Belegung A : {A1 , . . . , An } → {0, 1}, die F0 erfüllt, dann ist A0 ein Modell
für F , wobei A0 wie folgt definiert ist:
A(B) falls B ∈ {A1 , . . . , An }
0
A (B) =
0
falls B = An+1
Die Existenz des Modells A0 steht aber im Widerspruch zur angenommenen Unerfüllbarkeit von F .
Deshalb kann F0 nicht erfüllbar sein, aus dem selben Grund ist auch F1 unerfüllbar.
Man weiss nun, dass F0 und F1 unerfüllbar sind, daher kann auf sie die Induktionsvoraussetzung
angewandt werden und es gilt 2 ∈ Res∗ (F0 ) und 2 ∈ Res∗ (F1 ). Das heisst auch, dass es Klauseln
K1 , . . . , Km geben muss mit:
Km = 2 und für i = 1, . . . , m gilt: Ki ∈ F0 oder Ki ist Resolvent zweier Klauseln Ka , Kb mit a, b < i.
D. h. es gibt für F0 eine Folge von Klausel K1 , . . . , Km , die zur leeren Klausel führt. Für F1 gibt es
ebenfalls eine Folge K10 , . . . , Kt0 .
Einige der Klauseln Ki entstanden aus F wobei das Vorkommen des Literals An+1 gestrichen wurde.
Jetzt wird die ursprüngliche Klausel Ki ∪{An+1 } wieder hergestellt und An+1 bei den Resolutionsschritten mitgeführt. Es kann nur passieren, dass im Laufe der Resolutionsschritte die leere Klausel auftaucht,
dann ist alles gezeigt. Wenn dies nicht passiert, ist am Ende auf jeden Fall {A n+1 } ∈ Res∗ (F ).
Durch das Wiedereinfügen der von ¬An+1 in die Folge K10 , . . . , Kt0 , ergibt sich am Ende auf jeden Fall
{¬An+1 } ∈ Res∗ (F ).
Jetzt braucht nur noch ein Resolutionsschritt durchgeführte werden
{An+1 }
{¬An+1 }
2
und es gilt 2 ∈ Res∗ (F ).
11.2.6
i Woraus besteht die Aussagenlogik (Syntax/Semantik)?
Syntax. Eine atomare Formel hat die Form Ai , wobei i = 1, 2 . . .. Formeln werden induktiv definiert.
1. Alle atomaren Formeln sind Formeln.
2. Für alle Formeln F und G sind (F ∧ G) und (F ∨ G) Formeln.
3. Für jede Formel F ist ¬F eine Formel.
Semantik. Es gibt eine Funktion A, die die atomaren Formeln auf die Menge der Wahrheitswerte
{0, 1} abbildet. Desweiteren gibt es eine Funktion  die Menge der Formeln auf die Wahrheitswerte abbildet. Die Unterscheidung zwischen A und  hat formale Gründe, da  einen grösseren
Definitionsbereich als A hat. In einigen Bücher wird diese Unterscheidung nicht gemacht und in
allen wird sie früher oder später weggelassen. Die Semantik ist wie folgt definiert.
1. für jede atomare
2. Â((F ∧ G)) =
3. Â((F ∨ G)) =
Formel A ist Â(A) = A(A).
1, falls Â(F ) = 1 und Â(G) = 1
0, sonst
1,
0,
falls Â(F ) = 1 oder Â(G) = 1
sonst
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
151
Kapitel 11. Logik
4. Â((¬F )) =
11.2.7
1,
0,
falls Â(F ) = 0
sonst
Was sind die minimalen Junktoren?
Sowohl mit NAND als auch NOR können ∧, ∨, ¬ dargestellt werden.
11.2.8
Was ist eine Basis?
Eine Menge O von Operatoren ist eine Basis (vollständig) falls es zu jeder Funktion f : W n → W, n ≥ 1
eine Formel F gibt, sodass
F enthält nur Operatoren aus O und atomare Aussagen A1 , . . . An
für alle zu F passenden Belegungen A gilt f (A(A1 ), . . . , A(An )) = A(F ).
11.2.9
Erklären Sie die Konjunktive Normalform.
Eine Formel ist in konjunktiver Normalform, wenn sie folgende Form hat:
F = (L1,1 ∨ . . . ∨ L1,n1 ) ∧ . . . ∧ (Lk,1 ∨ . . . ∨ Lk,nk )
Beweis dafür, dass es für jede Formel eine konjunktive Normalform gibt, ist ein Induktionsbeweis über
den Formelaufbau.
Algorithmus zum Erzeugen der KNF:
1. Ersetze in F jedes Vorkommen einer Teilformel der Bauart
¬¬G durch G
¬(G ∧ H) durch (¬G ∨ ¬H)
¬(G ∨ H)
durch
(¬G ∧ ¬H)
bis keine derartige Teilformel mehr vorkommt.
2. Ersetze in F jedes Vorkommen einer Teilformel der Bauart
(F ∨ (G ∧ H))
((F ∧ G) ∨ H)
durch
durch
((F ∨ G) ∧ (F ∨ H))
((F ∨ h) ∧ (G ∨ H))
bis keine derartige Teilformel mehr vorkommt.
Die Formel ist nun in KNF. Es kann allerdings sein, dass noch überflüssige Disjunktion vorkommen.
Diese jedoch zulässig, da es sich um Tautologien handelt.
Beispiel:
(¬A → B) ∧ ((A ∧ ¬C) → B)
= (A ∨ B) ∧ (¬(A ∧ ¬C) ∨ B)
= (A ∨ B) ∧ ((¬A ∨ C) ∨ B)
= (A ∨ B) ∧ (¬A ∨ C ∨ B)
11.2.10 Erklären Sie die Disjunktive Normalform.
Eine Formel ist in disjunktiver Normalform, wenn sie folgende Form hat:
F = (L1,1 ∧ . . . ∧ L1,n1 ) ∨ . . . ∨ (Lk,1 ∧ . . . ∧ Lk,nk )
Beweis dafür, dass es für jede Formel eine disjunktive Normalform gibt, ist ein Induktionsbeweis über
den Formelaufbau.
152
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.2. Aussagenlogik
i Was ist der Endlichkeitssatz?
11.2.11 Eine Menge M von Formel ist erfüllbar genau dann, wenn jede der endlichen Teilmengen von M erfüllbar
ist.
i Beweis des Endlichkeitssatzes?
11.2.12 Die Richtung von links nach rechts ist einfach. Jedes Modell für M ist ein Modell für jede Teilmenge
von M und damit auch für jede endliche Teilmenge. In die andere Richtung wird es kompliziert, daher
zerlegt man den Beweis am Besten in mehrere Schritte.
1. Erst nochmal die Aufgabe verdeutlichen: Man nimmt an, jede endliche Teilmenge von M ist
erfüllbar, dass heisst sie hat ein Modell. Die Aufgabe ist nun aus diesen unendlich vielen Modellen ein Modell für M zu konstruieren. Wenn das gelingt, ist auch die Richtung von rechts nach
links bewiesen.
2. Für jedes n ≥ 1 sei Mn die Menge der Formel in M, die nur die atomaren Formeln A1 , . . . An
enthalten. Jede dieser Mengen Mn ist wieder unendlich, da es unendlich viele Möglichkeiten gibt n
n
atomare Formeln zu einer Formel zusammen zubauen. Aber es gibt höchstens k ≤ 22 verschiedene
Formeln in M, die nicht äquivalent zueinander sind.
n
Wieso? Für eine Formel mit n atomaren Formeln kann man höchstens 22 verschiedene Wahrheitstafeln aufstellen. Für jede atomare Formel zwei Möglichkeiten, daher 2n und dann noch pro
n
Belegung wahr oder ’falsch, macht 22 verschiedene Wahrheitstafeln.
Man nennt diese nicht äquivalenten Formeln in Mn jetzt F1 . . . Fk , da es ja nicht mehr als k gibt.
Jetzt kann man für jede Formel F aus Mn eine zu ihr äquivalente Formel Fi mit i ≤ k finden.
Formell: Für jedes F ∈ Mn gibt es ein i ≤ k mit Fi ≡ F .
Jedes Modell was Modell für die Formelmenge {F1 , . . . , Fk } ist, muss daher auch Modell für Mn
sein. Das ist schon mal nicht schlecht, das Modell für die endliche Formelmenge {F1 , . . . , Fk } ist
auch Modell für die unendliche Formelmenge Mn (damit ist leider noch nichts bewiesen). Das
Modell für die Formelmenge Mn heisst ab jetzt An . Dieses Modell hat eine wichtige Eigenschaft.
Da M1 ⊆ M2 ⊆ . . . ⊆ Mn , ist An nicht nur Modell für Mn , sondern auch für M1 , M2 , . . . , Mn−1 .
3. Eigentlich sucht man ja nach dem Modell A für die Menge M. Diese Modell muss nun aus den
Modellen Ai zusammengesetzt (konstruiert) werden.
Zur Schreibweise: Das gesuchte Modell A ist eine Funktion die von den atomaren Formeln A n auf
die Wahrheitswerte {0, 1} abbildet. Diese Funktion kann auch in Relationenschreibweise geschrieben
werden, wobei A(An ) = 1 durch (An , 1) und A(An ) = 0 durch (An , 0) ausgedrückt wird. Das hat
den Vorteil das man die Mengenoperation ∪ zum Erweitern des Definitionsbereichs verwenden kann.
Die Belegung B = {(A1 , 1)} ∪ {(A2 , 0)} z. B. weist dem Atom A1 1 und dem Atom A2 0 zu.
Man gibt nun einen Algorithmus an, der das gesuchte Modell A konstruiert. Im letzten Schritt
wird dann gezeigt, dass dieses Modell auch tatsächlich ein Modell für M ist.
4. Dieser Algorithmus baut das Modell A in mehreren Stufen auf. In der ersten Stufe wird A einfach
auf die leere Menge gesetzt, enthält also für kein einziges Atom eine Belegung. Zusätzlich gibt es
eine unendliche Indexmenge I, die zu Beginn auf I = {1, 2, . . .} gesetzt wird.
01
02
04
05
06
07
Stufe 0:
A←∅
I ← {1, 2, 3, . . .}
Stufe n > 0:
if (es gibt unendlich viele Indizes i ∈ I mit Ai (An ) = 1) {
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
153
Kapitel 11. Logik
08
09
10
11
12
13
A ← A ∪ {(An , 1)}
I ← I − {i | Ai (An ) 6= 1}
} else {
A ← A ∪ {(An , 0)}
I ← I − {i | Ai (An ) 6= 0}
}
Was macht der Algorithmus jetzt in der Stufe 1? Zuerst kommt die IF-Abfrage in Zeile 7. Diese
Abfrage ist so nicht programmierbar (auf jeden Fall nicht in endlicher Zeit), trotzdem wird jetzt
angenommen, das diese Anfrage immer ein Ergebnis liefert und sich der Algorithmus somit immer
für einen der beiden Zweige entscheidet. Man kann sich die Abfrage so vorstellen: Das Atom A n
(in der ersten Stufe A1 ) wird in alle Modelle Ai eingesetzt und überprüft, ob unendlich oft 1
herauskommt.
Zur Erinnerung: Die Ai sind die Modelle für die Formelmengen Mn , die in Schritt 2 definiert
wurden.
Auch wenn diese Abfrage nicht programmierbar ist, liefert sie immer eine Antwort, entweder es gibt
unendliche viele Modelle Ai für die A( A1 ) = 1 oder nicht. Angenommen es gibt unendlich viele,
was passiert dann? Das Modell A (das bis jetzt aus der leeren Menge besteht) wird um (A 1 , 1)
erweitert. Es weist also fortan dem Atom A1 den Wert 1 zu.
Was in Zeile 9 mit der Indexmenge I passiert, wird gleich erklärt. Jetzt erst mal zu dem ELSEZweig. Falls nicht unendlich viele Modelle Ai gibt, die A1 1 zuweisen, dann wird der ELSE-Zweig
ausgeführt. Dieser mach genau dasselbe nur erweitert er A um (A1 , 0). Das Modell weist A1 also
fortan den Wert 0 zu.
Also, was soll die Veränderung der Indexmenge I? Der Grund für die Veränderung der Indexmenge
liegt genau in dem Wort fortan im letzten Absatz. Wenn das Modell dem Atom A1 den Wert
1 zuweist, dann soll das im nächsten Schritt auch noch so bleiben. Im nächsten Schritt n = 2
sucht man nach unendlich vielen Modellen Ai für die Ai (A2 ) = 1 ist. Diese Modellen sollen aber
natürlich nicht dem widersprechen, was in Schritt 1 bereits fix gemacht wurde. Ein Modell der Form
Ai = {(A1 , 0), (A2 , 1), . . .} ist also unbrauchbar, da es A1 nicht den Wert 1 sondern 0 zuordnet.
Deswegen geht man brutal vor und verwirft im Schritt 1 gleich alle Modelle, die so aussehen. Das
wird erreicht, indem einfach die Indizes der untauglichen Modelle gestrichen werden. Genau das
passiert in Zeile 9. Interessant ist, dass dies einfach so geht, aber die unendliche Anzahl an Modellen
Ai macht’s möglich.
5. Das Modell A für die Formelmenge M wurde nun konstruiert. Es muss nur noch gezeigt werden,
dass es sich auch tatsächlich um ein Modell handelt.
Man nimmt sich eine beliebige Formel F aus M. In F können nur endlich viele atomare Formel
vorkommen, z. B. l Stück. Das heisst F setzt sich zusammen aus den atomaren Formeln A1 , . . . , Al .
Das heisst, F ist Element von Ml und damit auch von Ml+1 ⊆ Ml+2 ⊆ . . .. Daraus folgt, dass Al
und Al+1 , Al+2 , . . . Modelle für F sind. Wichtig ist nun, dass die Indexmenge I in jedem Schritt
zwar ausgedünnt wird, da I aber zu Beginn unendlich ist, bleibt sie immer unendlich. Das heisst
aber auch, das in der Stufe l des Algorithmus immer noch unendliche viele Indizes i ∈ I vorhanden
sind. Wenn es noch unendlich viele Indizes gibt, dann gibt es aber sicher auch eins mit i ≥ l. Für
diese i gilt: Ai (A1 ) = A(A1 ), . . . , Ai (Al ) = A(Al ) und deshalb ist A ein Modell für F . Da wir das
F vollkommenen beliebig aus M gewählt haben, gilt diese Schlussfolgerung für alle F und damit
ist A Modell für M.
i Obere Schranke für Komplexität der Resolution mit Beweis.
11.2.13 Sei F eine Klauselmenge mit den Atomformeln A1 , . . . , An . Jede der Atomformeln kann in einer Klausel
positive vorkommen, negativ vorkommen, positive und negativ vorkommen oder gar nicht vorkommen.
Diese vier Möglichkeiten führen zu höchstens 4n verschiedenen Klauseln in Res∗ (F ). In jedem Schritt
154
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.2. Aussagenlogik
von Resi (F ) nach Resi+1 (F ) kann nur eine Klausel hinzukommen. Daher ist 4n eine grobe obere
Schranke für die Komplexität.
11.2.14 Berechenbarkeit der Aussagenlogik im Vergleich zur Prädikatenlogik?
Die Aussagenlogik ist im Gegensatz zur Prädikatenlogik entscheidbar.
i Ist die Aussagenlogik entscheidbar?
11.2.15 Die Aussagenlogik ist entscheidbar, da mit Hilfe der Wahrheitstabelle jede Formel entscheidbar ist.
11.2.16 Was können sie über Aussagenkalküle sagen?
Hilbert-Kalkül.
technisch sehr einfach
direkt kaum benutzbar
Natürliches Schliessen.
technisch Aufwendiger, es gibt lokale Annahmen
korrespondiert zum
natürlichen/mathematischen Beweisen
direkt mit Hilbert-Kalkül verwandt
Problem: Beweissuche (→ E hat nicht die Teilformeleigenschaft)
aber jede Tautologie hat einen Beweis mit Teilformeleigenschaft
Sequenzen-Kalkül.
technisch aufwendiger
Ideal zur Beweissuche
liefert Gegenmodell
Für Genaueres siehe (11.2.3), (11.2.23), (11.2.24) und (11.2.25).
11.2.17 Wozu dient ein Kalkül?
Ein Kalkül ist eine Kollektion rein mechanisch anzuwendender syntaktischer Umformungsregeln.
Die Aufgabenstellung ist der Nachweis der Unerfüllbarkeit einer Formel. ein Kalkül muss korrekt und
vollständig sein.
11.2.18 Nennen Sie das Deduktionstheorem der Aussagenlogik.
Seien F und G aussagenlogische Formeln und M eine Menge von Formeln, dann gilt:
M ∪ {F } |= G
11.2.19 Bilden
nicht und
=⇒
M |= (F → G)
und eine Basis?
Ja. A ∨ B kann dargestellt werden durch ¬(¬A ∧ ¬B).
11.2.20 Gibt es eine Basis mit nur einem Operator?
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
155
Kapitel 11. Logik
Ja, NAND und NOR. Für NAND gilt:
¬F
F ∧G
F ∨G
= NAND(F, F )
= ¬(F ∧ F )
= ¬F
= NAND(NAND(F, G), NAND(F, G))
= NAND(¬(F ∧ G), ¬(F ∧ G))
= ¬((¬(F ∧ G)) ∧ (¬(F ∧ G)))
= ¬(¬(F ∧ G))
= F ∧G
= NAND(NAND(F, F ), NAND(G, G)
NAND(¬F, ¬G)
¬(¬F ∧ ¬G)
=
=
F ∨G
=
Für NOR gilt:
¬F
F ∧G
= NOR(F, F )
= ¬(F ∨ F )
= ¬F
= NOR(NOR(F, F ), NOR(G, G))
= NOR(¬F, ¬G)
=
=
F ∨F
¬(¬F ∨ ¬G)
F ∧G
= NOR(NOR(F, G), NOR(F, G))
= NOR(¬(F ∨ G), ¬(F ∨ G))
=
=
=
¬(¬(F ∨ G) ∨ ¬(F ∨ G))
¬(¬(F ∨ G))
F ∨G
11.2.21 Erfüllbarkeitstest für Hornformeln?
Eine Hornformel F kann mit folgendem Algorithmus auf Erfüllbarkeit getestet werden.
1. Für jede Teilformel der Form (1 → A), markiere A.
2. solange es in F eine Teilformel G der Form (A1 ∧ . . . ∧ An → B) oder (A1 ∧ . . . ∧ An → 0) wobei
alle A1 , . . . An bereits markiert sind, B jedoch nicht, tue folgendes:
Falls G die erste Form hat, markiere jedes Vorkommen von B, andernfalls unerfüllbar ausgeben
und anhalten.
3. Wenn der Algorithmus bis hier läuft, gibt erfüllbar aus und stoppe. Die erfüllende Belegung
wird durch die Markierung angezeigt. A(Ai ) = 1 falls Ai markiert ist.
Dieser Algorithmus ist korrekt und hat Laufzeit O(n), wobei n die Anzahl der Atome ist.
11.2.22 Was ist der Modus Ponens?
Eine Regel des natürlichen Schliessens:
φ
φ→ψ
(→−e)
ψ
i Erzählen Sie etwas zum natürlichen Schliessen.
11.2.23 156
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.2. Aussagenlogik
Im Gegensatz zum Hilbert-Kalkül erlaubt natürliches Schliessen das Schliessen unter lokalen Annahmen.
Beim natürlichen Schliessen werden Herleitungsbäume konstruiert. Diese werden mit ihrer Wurzel unten
und den Blätter oben geschrieben. Formeln an den Blättern heissen Annahmen, die Formeln an der
Wurzel heisst Konklusion. Annahmen können entweder gestrichen oder offen sein. Die Menge der
korrekten Herleitungsbäume ist induktiv definiert:
1. F ist ein Beweisbaum mit der offenen Annahme F .
2. Durch die Regeln können induktiv neue Beweisbäume gebildet werden.
Die Regeln.
Konjunktion. Eine Konjunktion kann eingeführt
A B
(∧−i)
A∧B
oder eliminiert werden
A∧B
A∧B
(∧−e)
(∧−e).
A
B
Implikation. Wenn B eine Herleitung von A ist, kann man A → B schreiben und die Annahme A
streichen.
[A]
..
.
B
(→−i)
A→B
Zur Elimination einer Implikation dient der Modus Ponens.
A→B
(→−e)
B
A
Disjunktion. Eine Disjunktion kann durch eine der beiden folgenden Regeln eingeführt werden.
A
(∨−i)
A∨B
B
(∨−i)
A∨B
Um aus einer Disjunktion A ∨ B etwas schliessen zu können, muss man es sowohl aus A wie aus B
schliessen können.
[A] [B]
..
..
.
.
A∨B
C
C
(∨−e)
C
Negation. Die Verneinung einer Annahme ist gerechtfertigt, wenn ihre Annahme zu einem Widerspruch geführt hat.
[A]
..
.
⊥
(¬−i)
¬A
Eine Aussage und ihre Verneinung können nicht gleichzeitig gelten.
A
¬A
(¬−e)
⊥
Verum. Die wahre Aussage darf immer behauptet werden.
A
(>−i)
>
Falsum. Aus der falschen Aussage darf alles gefolgert werden.
⊥
(⊥−e)
A
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
157
Kapitel 11. Logik
Reductio ad absurdum. Der Widerspruchsbeweis
[¬A]
..
.
⊥
A
(raa)
Beispiel. Die Folgerungsbeziehung ¬A |= A → B ist richtig, das Beispiel zeigt einen Herleitungsbaum.
¬A
[A]
⊥
B
A→B
(¬−e)
(⊥−e)
(→−i)
Hier wurde mit der Annahme ¬A begonnen und die temporäre Annahme A hinzugenommen. Daraus
kann ⊥ geschlossen werden. Aus ⊥ kann wiederum alles geschlossen werden, in diesem Falle B. Im
letzten Schritt wird → eingeführt, dafür darf die temporäre Annahme A gestrichen werden.
Korrektheit und Vollständigkeit. Natürliches Schliessen und der Hilbert-Kalkül sind äquivalent. Da der
Hilbert-Kalkül korrekt ist, ist auch natürliches Schliessen korrekt. Natürliches Schliessen ist vollständig,
da es die Resolution simulieren kann und die Resolution vollständig ist.
11.2.24 Erzählen Sie etwas zu Hilbert-Kalkülen.
Hilbert-Kalküle sind sehr einfach, eignen sich aber schlecht zur Beweissuche.
Ein Hilbert-Kalkül besteht aus einer Menge von Formeln (Axiomen) und einer Menge von Schlussregeln der Form
F1 . . . F n
Prämissen
=
.
F
Konklusion
Wenn n = 0 dann ist die Regel ein Axiom.
Eine Herleitung einer Formel F aus einer Formelmenge M ist eine Sequenz F1 , . . . , Fk mit Fk = F
und für i ≤ k gilt
Fi ist ein Axiom oder
n
es gibt eine Regel G1 ...G
so dass {G1 , . . . Gn } ⊆ {F1 , . . . Fi−1 }, d. h. Fi wurde auch aus F
G
hergeleitet.
Man schreibt M `H F . Die Herleitung ist ein Beweis von F .
Es gibt zwei Grundaxiome.
A1 F → (G → F ) für beliebige Formeln F, G
A2 (F → G → H) → (F → G) → F → H Kettenschluss
Eine Schlussregel, den Modus Ponens.
F →G
G
F
Beispiel. Die Herleitung von `H A → A.
1.
2.
3.
4.
5.
(A → (A → A) → A) → (A → (A → A)) → A → A
A → ((A → A) → A)
(A → A → A) → A → A
A→A→A
A→A
(A2)
(A1)
(MP 1,2)
(A1)
(MP 3,4)
Deduktionstheorem. In jedem Hilbert-Kalkül, das mindestens die Axiome A1 und A2 enthält und
nur den Modus Ponens als Regel besitzt gilt
M ∪ {F } `H G genau dann, wenn M `H F → G
158
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.2. Aussagenlogik
Vollständiges Axiomensystem.
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
F → (G → F )
(F → G → H) → (F → G) → F → H
F ∧G→F
F ∧G→G
F →G→F ∧G
F →F ∨G
G→F ∨G
F ∨ G → (F → H) → (G → H) → H
(¬F → ⊥) → F
¬F → F → ⊥
(F → ⊥) → ¬F
Korrektheit. Es gilt
`H F
⇒
|= F
Der Beweis geht mit Induktion über die Länge der Herleitung `H F
1. Alle Axiome sind Tautologien.
2. Der Modus Ponens überführt Tautologien in Tautologien.
Vollständigkeit. Es gilt
|= F
⇒
`H F
Beweis.
1. Hilbert-Kalkül ist äquivalent zum Natürlichen Schliessen.
2. Natürliches Schliessen kann Resolution simulieren.
3. Resolution ist vollständig, siehe 11.2.5.
11.2.25 Erzählen Sie etwas zum Sequenzen-Kalkül.
Das Ziel des Sequenzen-Kalküls ist die Beweissuche. Es werden immer Sequenzen der Form Γ ⇒ ∆
bewiesen wobei Γ, ∆ Multimengen von Formel sind. Intuitiv gilt, F1 , . . . Fn ⇒ G1 , . . . , Gn ist herleitbar
falls
|= F1 ∧ . . . ∧ Fn → G1 ∨ . . . ∨ Gn
gilt. Dieser Zusammenhang wird wie folgt notiert:
|Γ ⇒ ∆| =
^
Γ→
_
∆
Es gibt für jeden Junktor eine rechte und eine linke Regel:
Konjunktion.
Γ, F, G ⇒ ∆
(∧−L)
Γ, F ∧ G ⇒ ∆
Γ ⇒ ∆, F Γ ⇒ ∆, G
(∧−R).
Γ ⇒ ∆, F ∧ G
Disjunktion.
Γ, F ⇒ ∆ Γ, G ⇒ ∆
(∨−L)
Γ, F ∨ G ⇒ ∆
Γ ⇒ ∆, F, G
(∨−R).
Γ ⇒ ∆, F ∨ G
Implikation.
Γ ⇒ F, ∆ Γ, G ⇒ ∆
(→−L)
Γ, F → G ⇒ ∆
Γ, F ⇒ ∆, G
(→−R).
Γ ⇒ ∆, F → G
Negation.
Γ ⇒ F, ∆
(¬−L)
Γ, ¬F ⇒ ∆
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
Γ, F ⇒ ∆
(¬−R).
Γ ⇒ ∆, ¬F
159
Kapitel 11. Logik
Da bei jeder Regel die Formeln der Konklusion auch in der Prämisse stehen, ist die Rückwärtsanwendung
einer deterministisch, Dies nennt man Teilformeleigenschaft.
Für jede Regel
S1
Sn
S
und jede passende Belegung A gilt
A |= |S| genau dann, wenn A |= |S1 | und . . . und A |= |Sn |
Die Korrektheit des Sequenzen-Kalküls, also dass `G S folgt, dass |= |S| gilt, wird mit einem Induktionsbeweis über die Grösse der Herleitung von S gezeigt.
Das Sequenzen-Kalküls hat eine weitere interessante Eigenschaft: Jeder fehlgeschlagene Beweisversuch
für S liefert ein Gegenmodell für |S|, das heisst ein Modell für ¬|S|. Dadurch ist auch gleich die
Vollständigkeit beweisen, da jeder Beweisversuch immer zu einem Modell für |S| oder ¬|S| führt.
Beispiel. Aufgabe ist es zu zeigen, dass ⇒ A ∨ ¬A gilt.
Axiom
A⇒A
(¬−R)
⇒ A, ¬A
(∨−R)
⇒ A ∨ ¬A
11.2.26 Was ist eine Wahrheitstafel?
Eine Wahrheitstafel zeigt alles passenden Belegungen einer Formel.
11.2.27 Ist die Formel ((A → B) → C) ↔ (A → (B → C)) eine Tautologie?
Nein, das würde bedeuten, dass das Assoziativgesetz für die Implikation gilt und das tut es nicht.
11.3
11.3.1
Prädikatenlogik
Wie gehen Sie vor, wenn Sie die Unerfüllbarkeit einer prädikatenlogischen Formel F zeigen möchten
Um die prädikatenlogische Resolution auf eine Formel F anzuwenden, müssen folgende Schritte durchlaufen werden.
1. Skolemnormalform. Um mit der Formel F überhaupt etwas Anfangen zu können muss zuerst die
Skolemform der Formel erstellt werden. Den Weg dorthin kann man wieder in mehrere Schritte
zerlegen und wird an der Formel
F = ¬∃x P (x, z) ∨ ∀yQ x, f (y) ∨ ∀yP g(z, y), z
vorgeführt.
a) Bereinigung. F wird durch gebundenes Umbenennen der Variablen in eine äquivalente , bereinigte Form F1 überführt. Eine Formel ist in bereinigter Form wenn es keine Variablen mehr gibt
die sowohl frei und gebunden vorkommen und hinter allen Quantoren verschiedene Variablen
stehen. Das y im zweiten Disjunktionsglied wird in w umbenannt und es ergibt sich:
F1 = ¬∃x P (x, z) ∨ ∀yQ x, f (y) ∨ ∀wP g(z, w), z
Diese Formel ist äquivalent zu F .
b) Freie Variablen beseitigen. Falls in der Formel F1 noch freie Variable y1 , . . . , yn vorkommen,
ersetzt man F1 durch F2 = ∃y1 . . . ∃yn F1 . F2 ist erfüllbarkeitsäquivalent zu F1 und F2 . Im
Beispiel ist z eine ungebundene Variable deshalb führt man ∃z ein:
F2 = ∃z ¬∃x P (x, z) ∨ ∀yQ x, f (y) ∨ ∀wP g(z, w), z
160
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.3. Prädikatenlogik
c) Pränexform. Jetzt wird eine zu F2 äquivalent und damit zu F erfüllbarkeitsäquivalente Formel
F3 in Pränexform hergestellt. Eine Formel ist in Pränexform, wenn alle ihre Quantoren am
Anfang der Formel stehen. Das ergibt
F3 = ∃z∀x∃y∀w ¬P (x, z) ∧ ¬Q x, f (y) ∨ P g(z, w), z
d) Skolemform. Jetzt werden die Existenzquantoren durch den Übergang zur Skolemform eliminiert. Die neue Formel F4 ist weiterhin erfüllbarkeitsäquivalent zu F . In diesem Falle wird der
z durch a und y durch h(x) substituiert.
F4 = ∀x∀w
¬P (x, a) ∧ ¬Q x, f (h(x))
∨ P g(a, w), a
e) KNF. Die Matrix von F4 wird in KNF umgeformt:
F5 = ∀x∀y((P (g(a, w), a) ∨ ¬P (x, a)) ∧ (P (g(a, w), a) ∨ ¬Q(x, f (h(x)))))
Als Klauselmenge dargestellt:
F5∗ = {{P (g(a, w), a), ¬P (x, a)}, {P (g(a, w), a), ¬Q(x, f (h(x)))}}
Bis jetzt ist noch nicht wirklich etwas passiert. Diese Schritte galten nur der Erstellung der Skolemform, die im weiteren Verlauf benötigt wird. Wichtig ist, dass die entstandene Formel F5 trotz
aller Umformungen erfüllbarkeitsäquivalent zu F ist.
→ Motivation der nächsten Schritte. Die nächsten Schritte hängen jetzt erst mal ein bisschen in
der Luft. Wichtig ist, nicht aus den Augen zu verlieren, das es im Endeffekt um das Zeigen der
Unerfüllbarkeit geht. Um die Unerfüllbarkeit zu zeigen benötigt man eine Menge E(F ) namens
Herbrand-Expansion. Die nächsten Schritte beschäftigen sich mit dem Finden dieser Menge. Das
kann man sich am besten vorstellen, wenn man vom Satz von Herbrand (11.3.17) zurück denkt.
Dieser Satz besagt, dass eine Aussage in Skolemform F genau dann unerfüllbar ist, wenn es eine
endliche Teilmenge von E(F ) (der Herbrand-Expansion) gibt, die im aussagenlogischen Sinne unerfüllbar ist. Der Beweis dieses Satzes hängt aber davon ab, ob eine erfüllbare Formel ein Modell
mit abzählbarer Grundmenge besitzt. Das dem so ist, besagt der Satz von Löwenheim-Skolem
(11.3.21). Er besagt, dass jede erfüllbare prädikatenlogische Formel ein Modell mit abzählbarer
Grundmenge besitzt und zwar ein Herbrand-Modell, das eine Herbrand-Struktur ist.
2. Herbrand-Struktur. Zum Beispiel ist die Herbrand-Struktur (11.3.10) für die Formel F
F = ∀x∀y∀zP (x, f (y), g(z, x))
wie folgt definiert.
UA = D(F ) = {a, f (a), g(a, a), f (g(a, a)), f (f (a)), g(a, f (a), g(f (a), a, . . .}
und es gilt:
f A (a)
A
f (f (a))
A
f (g(a, a))
=
f (a)
= f (f (a))
= f (g(a, a))
..
.
3. Herbrand-Expansion. Jetzt wird die Herbrand-Expansion bestimmt. Die Herbrand-Expansion entsteht in dem die Variablen in F ∗ in jeder möglichen weise durch die Terme in D(F ) substituiert
werden. Für die Formel
F = ∀x∀y∀zP (x, f (y), g(z, x))
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
161
Kapitel 11. Logik
ergeben sich
P (a, f (a), g(a, a))
P (f (a), f (a), g(a, f (a)))
P (a, f (f (a)), g(a, a))
durch [x/a][y/a][z/a]
durch [x/f (a)][y/a][x/a]
durch
..
.
[x/a][y/f (a)][x/a]
Nach dem Satz von Herbrand (11.3.17) ist eine Aussage F in Skolemform genau dann unerfüllbar,
wenn eine endliche Teilmenge von E(F ) im aussagenlogischen Sinne unerfüllbar ist. D. h. man
muss jetzt nur per Aussagenlogik zeigen, dass E(F ) unerfüllbar ist und ist fertig. Da kommt nun
die Resolution ins Spiel. Im Folgenden seien F1 , F2 . . . eine Aufzählung aller Formeln in E(F ).
4a. Grundresolution. Die Aufgabe ist nun zu zeigen, das E(F ) im aussagenlogischen Sinne unerfüllbar
ist. Dies kann sehr einfach mit dem Grundresolutionsalgorithmus durchgeführt werden (11.3.11).
Die Grundresolution arbeitet auf den Element von E(F ) und damit auf Grundinstanzen der Klausel
von F ∗ . Sie heissen Grundinstanzen, da alle Variablen durch variablenfreie Terme ersetzt wurden.
Beispiel. Gegeben ist die unerfüllbare Formel, ihre Matrix in Klauselform, D(F ) und E(F )
F
F∗
= ∀x(P (x) ∧ ¬P (f (x)))
= (P (x) ∧ ¬P (f (x)))
= {{P (x)}, {¬P (f (x))}}
D(F ) = {a, f (a), f (f (a)), . . .}
E(F ) = {(P (a) ∧ ¬P (f (a))), (P (f (a)) ∧ ¬P (f (a)))), . . .}
Schon die ersten beiden Substitutionen [x/a] und [x/f (a)] liefern eine unerfüllbare Klauselmenge.
{P (a)}
{¬P (f (a))}
{P (f (A))}
{¬P (f (f (a)))}
2
Die Grundresolution ist sehr ineffizient, da alle Grundsubstitutionen durch probiert werden müssen.
Eine Alternative bietet die prädikatenlogische Resolution.
4b. Prädikatenlogische Resolution. Wie gesagt ist die ausschliessliche Resolution von Grundinstanzen
sehr ineffizient, besser wäre es nur die Substitutionen durchzuführen, die auf dem Weg zum Ziel
liegen. Die Grundidee dabei ist, prädikatenlogische Resolventen aus prädikatenlogischen Klausel
zu erzeugen. Dabei ist mit jedem Resolutionsschritt ein Substitutionsschritt verbunden. Ziel ist es
wie bei der aussagenlogischen Resolution, bestimmte Literale in zwei Ausgangsklauseln zueinander
komplementär zu machen. Ziel hierbei ist es Substitutionen zu finden, die zwei Literale unifizieren.
Beispiel. Gegeben sind zwei prädikatenlogische Klauseln
K1
=
K2
=
{P (f (x)), ¬Q(z), P (z)}
{¬P (x), R(g(x), a)}
R ist ein prädikatenlogischer Resolvent von K1 , K2 wenn die drei Bedingungen von (11.3.16)
gelten. Ein prädikatenlogischer Resolvent von K1 , K2 ist
R = {¬Q(f (x)), R(g(f x)), a)}
R erfüllt die drei Bedingungen:
1. Es gibt zwei Substitutionen s1 und s2 , so dass K1 und K2 keine gemeinsamen Variablen
enthalten. Man wählt z. B. s1 = [ ] und s2 = [x/u]. Das ergibt
162
K1 s 1
=
K2 s 2
=
K1 [ ] = {P (f (x)), ¬Q(z), P (z)}
K2 [x/u] = {¬P (u), R(g(u), a)}
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.3. Prädikatenlogik
2. Jetzt muss sich eine Literalmenge aus K1 s1 , K2 s2 finden lassen, die unfizierbar ist. Eine Wahl
ist
L
{P (f (x)), P (z), ¬P (u) }
|
{z
} | {z }
aus K1 s1
aus K2 s2
= {¬P (f (x)), ¬P (z), ¬P (u)}
=
Mit dem Unifikationsalgorithmus kann nun der allgemeinste Unifikator sub bestimmt werden.
Dieser liefert in zwei Schritten sub = [z/f (x)][u/f (x)]
3. Wenn jetzt noch die dritte Bedingung gilt, handelt es sich bei R um einen Resolventen. Ein
Resolvent ist nur dann ein Resolvent, wenn er folgende Form hat.
R = ((K1 s1 − {L1 , . . . , Lm }) ∪ (K2 s2 − {L01 , . . . , L0n }))sub.
Einsetzen der obigen Klausel und Substitutionen ergibt
R
=
=
=
=
=
(({P (f (x)), ¬Q(z), P (z)} − {P (f (x)), P (z)})
∪ ({¬P (u), R(g(u), a)} − {¬P (u)}))[z/f (x)][u/f (x)]
({¬Q(z)} ∪ {R(g(u), a)})[z/f (x)][u/f (x)]
({¬Q(z), R(g(u), a)})[z/f (x)][u/f (x)]
({¬Q(f (x)), R(g(u), a)})[u/f (x)]
{¬Q(f (x)), R(g(f (x)), a)}
Die Abbildung zeigt den Resolutions-/Substitutionsschritt noch einmal graphisch.
{P (f (x)), ¬Q(z), P (x)}
{¬P (x), R(g(x), a)}
s1
s2
sub
= []
= [x/u]
= [z/f (x)][u/f (x)]
{¬Q(f (x)), R(g(f (x)), a)}
Auf diese Weise können nun nur die Substitutionsschritte durchgeführt werden, die zum Finden der
leeren Klausel benötigt werden.
11.3.2
Um was erweitert die Prädikatenlogik die Aussagenlogik?
Die Prädikatenlogik erweitert die Aussagenlogik um Quantoren, Funktions- und Prädikatensymbole.
11.3.3
Normalformen der Prädikatenlogik?
siehe 11.3.22, 11.3.23 und 11.3.26
11.3.4
i Ist die Herbrand-Expansion abzählbar?
Die Herbrand-Expansion entsteht in dem die Variablen in F ∗ in jeder möglichen weise durch die Terme
in D(F ) substituiert werden. Das D(F ) abzählbar ist, ist auch E(F ) abzählbar.
11.3.5
Ist die Prädikatenlogik entscheidbar?
Das Erfüllbarkeitsproblem der Prädikatenlogik ist nicht entscheidbar. Beweis durch Reduktion auf das
Postsche Korrespondenzproblem.
11.3.6
Nennen Sie mir ein Kalkül für die Prädikatenlogik?
Resolution.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
163
Kapitel 11. Logik
11.3.7
Was ist eine Struktur?
Eine Struktur is ein Paar A = (UA , IA ) wobei UA eine beliebige aber nicht leere Menge ist. IA ist eine
Abbildung, die
jedem k-stelligen Prädikatensymbol P ein k-stelliges Prädikat über UA zuordnet,
jedem k-stelligen Funktionssymbol f eine k-stellige Funktion auf UA zuordnet,
jeder Variablen x eine Element der Grundmenge UA zuordnet.
11.3.8
Prädikatenlogische Resolution mit Unifikation am Beispiel ∃x(P (x) → ∀xP (x)).
Dieses Beispiel ist so einfach, dass man wirklich Schritt für Schritt vor gehen kann, da das HerbrandUniversum endlich ist, kann man ganz in Ruhe die Herbrand-Expansion bestimmen und dann erst
resolvieren.
1. Skolemform. Um mit der Formel F überhaupt etwas Anfangen zu können muss zuerst die Skolemform der Formel erstellt werden. Zur Übersicht wird erstmal die Implikation ersetzt.
F = ∃x(P (x) → ∀xP (x)) = ∃x(¬P (x) ∨ ∀xP (x))
a) Bereinigung. F wird durch gebundenes Umbenennen der Variablen in eine äquivalente , bereinigte Form F1 überführt. Hier wurde die Variable beim Allquantor in y umbenannt. Es ergibt
sich:
F1 = ∃x(¬P (x) ∨ ∀yP (y))
Diese Formel ist äquivalent zu F .
b) Freie Variablen beseitigen. Die Formel enthält keine freien Variablen, der Schritt entfällt daher
und es gilt:
F2 = F1 = ∃x(¬P (x) ∨ ∀yP (y))
c) Pränexform. Jetzt wird eine zu F2 äquivalente und damit zu F erfüllbarkeitsäquivalente Formel
F3 in Pränexform hergestellt. Eine Formel ist in Pränexform, wenn alle ihre Quantoren am
Anfang der Formel stehen. Das ergibt
F3 = ∃x∀y(¬P (x) ∨ P (y))
d) Skolemform. Jetzt werden die Existenzquantoren durch den Übergang zur Skolemform eliminiert. Die neue Formel F4 ist weiterhin erfüllbarkeitsäquivalent zu F . In diesem Falle wird der
einzige Existenzquantor gestrichen und durch das nullstellige Funktionssymbol a ersetzt.
F4 = ∀y(¬P (a) ∨ P (y))
e) KNF. Die Matrix von F4 wird in KNF umgeformt und als Klauselmenge dargestellt. Da die
Matrix von F4 bereits in KNF ist, ergibt sich
F5 = F4 = ∀y(¬P (a) ∨ P (y))
Als Klauselmenge dargestellt:
F5∗ = {{¬P (a), P (y)}}
2. Herbrand-Struktur. In diesem Fall ist es sehr einfach das Herbrand-Universum zu bestimmen, da F
keine Funktionssymbol mit einer Stelligkeit grösser 0 enthält. Es gibt eine Konstante a. Sie ist das
einzige Element des Herbrand-Universums und es gilt:
D(F5 ) = {a}
3. Herbrand-Expansion. Jetzt wird die Herbrand-Expansion E(F5 ) bestimmt. Dies ist beim Beispiel
sehr einfach da D(F5 ) nur das einzige Element a hat und F5 nur eine Variable nämlich y hat. Also
ersetzt man y durch a und erhält
E(F5 ) = {F5∗ [y/a]} = {{¬P (a), P (a)}}
164
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.3. Prädikatenlogik
4. Resolution. Hier gibt es leider nichts zu resolvieren. Unerfüllbarkeit kann nicht gezeigt werden.
Diese geht aber nur wegen dem endlichen Herbrand-Universum.
11.3.9
Was ist das Herbrand-Universum?
Das Herbrand-Universum D(F ) einer Formel F in Skolemform ist die Menge aller variablenfreien Terme,
die aus allen Bestandteilen von F gebildet werden können. Es ist induktiv definiert:
1. Alle in F vorkommenden Konstanten sind in D(F ). Falls F keine Konstante enthält, so ist a in
D(F ).
2. Für jedes in F vorkommende n-stellige Funktionssymbol f und Terme t1 , . . . tn in D(F ) ist der
Term f (t1 , . . . tn ) in D(F ).
Beispiel. Gegeben seien die Formeln
F
G
= ∀x∀y∀zP (x, f (y), g(z, x))
= ∀x∀yQ(c, f (x), h(y, b))
Bei F liegt der Spezial fall vor, da F keine Konstante enthält wird a in das Herbrand-Universum
aufgenommen:
D(F ) = {a, f (a), g(a, a), f (g(a, a)), f (f (a)), g(a, f (a), g(f (a), a, . . .}
Bei G sind Konstanten c und b vorhanden, daher:
D(G) = {c, b, f (c), f (b), h(c, c), h(c, b), h(b, c), h(b, b), f (f (c)), f (f (b)), . . .}
Man sieht, das Herbrand-Universum ist unendlich, sobald die Formel ein Funktionssymbol mit einer
Stelligkeit > 0 enthält. Man sieht auch, dass es rekursiv aufzählbar ist.
11.3.10 Was ist eine Herbrand-Struktur?
Wenn F eine Aussage in Skolemform ist, dann heisst jede zu F passende Struktur A = (U A , IA ) eine
Herbrand-Struktur, falls folgendes gilt:
1. UA = D(F ) (das Herbrand-Universum)
2. für jedes in F vorkommende n-stellige Funktionssymbol f und t1 , . . . tn ∈ D(F ) ist f A (t1 , . . . tn ) =
f (t1 , . . . tn ).
Beispiel. Für die Formel
F = ∀x∀y∀zP (x, f (y), g(z, x))
ist
UA = D(F ) = {a, f (a), g(a, a), f (g(a, a)), f (f (a)), g(a, f (a), g(f (a), a, . . .}
und es gilt:
f A (a)
A
f (f (a))
f A (g(a, a))
= f (a)
= f (f (a))
= f (g(a, a))
..
.
Die Wahl von P A bleibt an dieser Stelle noch offen. Wichtig ist, dass durch Punkt 2 der Definition
Syntax und Semantik gleichgeschaltet werden. Die Interpretation eines Terms liefert den Term, es gilt
also A(t) = t.
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
165
Kapitel 11. Logik
11.3.11 Geben Sie den Grundresolutionsalgorithmus an.
Der Grundresolutionsalgorithmus ist ein Resolutionsalgorithmus, der wie der Gilmore-Algorithmus funktioniert. Wenn F eine prädikatenlogische Formel ist, bezeichnen F1 , F2 . . . alle Formel ihrer HerbrandExpansion E(F ). Der Algorithmus erhält als Eingabe die Mengen Fi .
Grundresolution(Fi )
1 i←0
2 M ←∅
3 do {
4
i←i+1
5
M ← M ∪ Fi
6
M ← Res∗ (M )
7 } until (2 ∈ M )
8 return unerfüllbar
Wenn die Formel F unerfüllbar ist, hält der Algorithmus nach endlich vielen Schritten.
11.3.12 Was ist eine Grundsubstitution?
Bei einer Grundsubstitution werden alle freien Variablen durch variablenfreie Terme ersetzt. Die Substitutionen zur Definition der Herbrand-Expansion sind Grundsubstitutionen.
11.3.13 Was ist ein Unifikator und was ist ein allgemeinster Unifikator?
Eine Substitution sub ist ein Unifikator einer endlichen Menge von Literalen L = {L 1 , . . . Lk }, falls
L1 sub = L2 sub = . . . = Lk sub. D. h. durch Anwendung der Substitution sub auf jedes Literal in L
entsteht ein und dasselbe Literal.
Man schreibt für diesen Sachverhalt auch |Lsub| = 1 sagt L ist unifizierbar. Ein Unifikator sub einer
Literalmenge L heisst allgemeinster Unifikator von L, falls für jeden Unifikator sub0 von L gilt, dass es
eine Substitution s gibt mit sub0 = subs. Wobei subs die Hintereinanderausführung der Substitution
subs und s beschreibt.
11.3.14 Wie funktioniert der Unifikationsalgorithmus?
Der Unifikationsalgorithmus überprüft ob eine Literalmenge L unifizierbar ist und gibt in diesem Fall
den allgemeinsten Unifikator aus. Als Eingabe erhält er eine nicht-leere Literalmenge L. In jedem
Schritt versucht er einen Unifikator zu finden, falls dies nicht möglich ist, bricht er ab, ansonsten wird
der neue Unifikator an den im vorherigen Schritt bestimmten, angehängt.
Unifikation(L)
01 sub ← [ ] //die leere Substitution
02 while (|Lsub| > 1) {
03
durchsuche die Literale in Lsub paarweise von links nach rechts bis erste
04
Position gefunden, wo sich zwei Literale L1 und L2 unterscheiden.
05
if (keines der beiden Zeichen ist Variable)
06
return nicht unifizierbar
07
else {
09
sei x die Variable und t der im anderen Literal beginnenden Term
10
if (x kommt in t vor)
11
return nicht unifizierbar
12
else
13
sub ← sub[x/t] //Hintereinanderausführung von sub und [x/t]
14
}
15 }
16 return allgemeinster Unifikator: ∪ sub
166
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.3. Prädikatenlogik
11.3.15 Was ist der Gödelsche Unvollständigkeitssatz?
Jedes Beweissystem für die Menge der wahren arithmetischen Formeln ist notwendigerweise unvollständig, d. h. es bleiben immer wahre arithmetische Formeln übrig, die nicht beweisbar sind.
11.3.16 Wie ist die Resolution der Prädikatenlogik definiert?
Seien K1, K2 und R prädikatenlogische Klauseln. Dann ist R ein prädikatenlogischer Resolvent von K1
und K2 , falls folgendes gilt:
1. Es gibt Substitutionen s1 und s2 , die Variablenumbennungen sind, so dass K1 s1 und K2 s2 keine
gemeinsamen Variablen enthalten.
2. Es gibt eine Menge von Literalen L1 , . . . , Lm ∈ K1 s1 (m ≥ 1) und L01 , . . . , L0n ∈ K2 s2 (n ≥ 1), so
dass L = {L1 , . . . , Lm , L01 , . . . , L0n } unifizierbar ist. sub ist der allgemeinste Unifikator von L.
3. R hat die Form
R = ((K1 s1 − {L1 , . . . , Lm }) ∪ (K2 s2 − {L01 , . . . , L0n }))sub.
11.3.17 Wie lautet der Satz von Herbrand?
Eine Aussage F in Skolemform ist unerfüllbar genau dann, wenn es eine endliche Teilmenge von E(F )
gibt, die im aussagenlogischen Sinne unerfüllbar ist.
11.3.18 Was ist das Lifting-Lemma?
Seien K1 , K2 zwei prädikatenlogische Klauseln und K10 , K20 seien beliebige Grundinstanzen hiervon, die
im aussagenlogischen Sinne resolvierbar sind, so dass R 0 ein Resolvent von K10 und K20 ist. Dann gibt
es einen prädikatenlogischen Resolventen R von K1 und K2 , so dass R0 eine Grundinstanz von R ist.
Das Lifting-Lemma wird zum Beweis der Vollständigkeit der prädikatenlogischen Resolution benötigt.
11.3.19 Wie lautet der Resolutionssatz der Prädikatenlogik?
Sei F eine Aussage in Skolemform mit der Matrix F ∗ in KNF. Dann gilt: F ist unerfüllbar genau dann,
wenn 2 ∈ Res∗ (F ∗ ).
11.3.20 Was sind Terme?
Term sind induktive definiert:
1. Jede Variable ist ein Term.
2. Falls f eine k-stellige Funktion und t1 , . . . tk Terme sind so ist auch f (t1 , . . . , tk ) ein Term.
i Satz von Löwenheim/Skolem mit Beweis?
11.3.21 Jede erfüllbare prädikatenlogische Formel besitzt ein Modell mit abzählbarer Grundmenge.
Beweis. Jede prädikatenlogische Formel F kann in eine erfüllbarkeitsäquivalente Aussage G in Skolemform umgewandelt werden. Diese Umformungen sind so, dass jedes Modell für G auch Modell für F
ist. Falls F erfüllbar ist, dann ist auch G erfüllbar und besitzt ein Herbrand-Modell, dass auch Modell
für F ist. Das Herbrand-Modell besitzt die abzählbare Grundmenge D(F ).
11.3.22 Welche Eigenschaften hat eine bereinigte Formel?
Eine Formel heisst bereinigt, wenn es keine Variable gibt, die sowohl gebunden als auch ungebunden
vorkommt. Ausserdem müssen hinter allen Quantoren unterschiedliche Variablen stehen. Diese Form
erreicht man durch gebundenes Umbenennen (11.3.24).
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
167
Kapitel 11. Logik
11.3.23 Was ist die Pränexform?
Eine Formel F ist in Pränexform falls sie folgende Bauart hat
Q1 y1 Q2 y2 . . . Q n yn F
wobei Qi ∈ {∃, ∀}. In F darf kein Quantor mehr vorkommen.
11.3.24 Was versteht man unter gebundenen Umbenennen?
Sei F = QxG mit Qi ∈ {∃, ∀}. Wenn y eine Variable ist, die in G nicht vorkommt, dann gilt
F ≡ QyG[x/y]
11.3.25 Was ist eine Matrix?
Die Matrix einer Formel F in Skolemform ist diejenige Formel, die man erhält, wenn man alle Quantoren
in F samt der dahinter stehenden Variablen streicht. Sie wird mit F ∗ bezeichnet.
11.3.26 Was ist die Skolemform?
Eine Formel ist in Skolemform, wenn sie bereinigt ist, in Pränexform ist und nur Allquantoren enthält.
11.3.27 Was ist eine Theorie?
Eine Theorie ist eine Menge von Formel T, die gegenüber Folgerbarkeit abgeschlossen ist. D.h. T
ist eine Theorie wenn für alle F1 , F2 , . . . Fn ∈ T und alle Formeln G gilt: wenn G eine Folgerung von
{F1 , F2 , . . . , Fn } ist, dann ist auch G ∈ T. Die Formel, die Element einer Theorie sind, heissen auch
Sätze.
11.3.28 Was ist ein Axiom?
Theorien können auf zwei Arten definiert werden:
1. Bei der modelltheoretischen Methode gibt man eine Struktur A vor und nimmt als Theorie alle
Formel die unter A gelten:
T h(A) = {F | A |= F }
2. Bei der axiomatischen Methode gibt man ein Axiomensystem, also eine Menge von Formeln M vor.
Diese Theorie besteht dann aus allen Formel die aus den Formel der Menge M folgerbar sind. Die
Element der Menge M heissen Axiome. Es gilt:
Cons(M) = {G | G folgt aus {F1 , . . . Fn } ∈ M}
11.4
11.4.1
Beweisideen
Unentscheidbarkeit der Prädikatenlogik.
Der Beweis erfolgt per Reduktion. Wir suchen einen Algorithmus der jedes beliebige Postsche Korrespondenzproblem (PCP) K in eine prädikatenlogische Formel F = FK überführt, so das K eine Lösung
besitzt, genau dann wenn F gültig ist. Das heisst man führt das Gültigkeitsproblem der Prädikatenlogik
auf PCP zurück. Falls das Gültigkeitsproblem entscheidbar wäre, müsste auch das PCP entscheidbar
sein. Die widerspricht den Kenntnissen der Berechenbarkeitstheorie.
11.4.2
Erfüllbarkeitsäquivalenz der Skolemform.
Beweis zeigt, dass jeder Durchlauf der Konstruktions-While-Schleife eine erfüllbarkeitsäquivalente Formel erzeugt. Dazu wird das Überführungslemma verwendet.
168
http://www.deissenboeck.de/faqs | DHP-FAQ v1.0
11.4. Beweisideen
11.4.3
Äquivalenz der Pränexform.
Bei der Umwandlung einer Formel F in eine Formel G in Pränexform gilt F ≡ G.
Beweis. Der Beweis ist ein Induktionsbeweis über den Formelaufbau. Hier ist alles sehr vereinfacht
dargestellt.
Induktionsanfang. Wenn F eine atomare Formel ist, dann ist F = G bereits in Pränexform und es gilt
F ≡ G.
Induktionsschritt. Es gibt 3 Fälle.
1. F hat die Form ¬F1 und G1 = Q1 y1 . . . Qn yn G0 ist die laut Induktionsvoraussetzung existierende
zu F1 äquivalent Formel. Dann gilt
F ≡ Q1 y1 . . . Qn yn ¬G0
Diese Formel ist in Pränexform.
2. F hat die Form (F1 ◦ F2 ). Es gibt zu F1 und F2 äquivalente Formeln G1 und G2 in Pränexform.
Die Formel
Q1 y1 . . . Qk yk Q01 z1 . . . Q0l zl (G01 ◦ G02 )
ist äquivalent zu F und in Pränexform.
3. F hat die Form QxF1 . Die gesucht Formel hat die Form
QxQ1 y1 . . . Qn yn F10
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
169
Literaturverzeichnis
[Cormen et al., 2000]
Cormen, Thomas H. et al. Introduction to Algorithms. MIT-Press, 2000
[DS-Faq, 2001]
DS-Faq. http://www.deissenboeck.de/faqs
[Duden Mathematik, 2000]
Duden Rechnen und Mathematik. Dudenverlag, 2000
[Duden Informatik, 1993]
Duden Informatik. 2. Aufl. Dudenverlag, 1993
[Graham et. al., 1989]
Graham, R.L., D.E. Knuth; Patashnik O. Concrete Mathematics. Addison
Wesley, 1989
[Kindler & Manthey, 2001]
Kinderl Ekkart; Manthey Steffen Skript zur Vorlesung Automaten, Formale
Sprachen und Berechenbarkeit WS 01/02.
[Ottmann & Widmayer, 2002]
Ottman, Thomas; Widmayer, Peter. Algorithmen und Datenstrukturen. 4.
Aufl. Spektrum, Akad. Verl., 2002
[Rechenberg & Pomberger, 1999] Rechenberg, Peter; Pomberger, Gustav (hrsg.) Informatik-Handbuch. 2. Aufl.
Hanser, 1999
[Schöning, 1997]
Schöning, Uwe. Theoretische Informatik – kurzgefaßt. 3. Aufl. Spektrum,
Akad. Verl., 1997
[Schöning, 2000]
Schöning, Uwe. Logik für Informatiker. 5. Aufl. Spektrum, Akad. Verl., 2000
DHP-FAQ v1.0 | http://www.deissenboeck.de/faqs
171

Documentos relacionados