Grundlagen der Informatik 1 und 2 - forster

Werbung
Grundlagen der Informatik 1 und 2
Zusammenfassung
Florian Forster
www.forster-florian.de
4. September 2002
Inhaltsverzeichnis
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
2
3
3
3
3
3
4
4
4
5
5
6
6
6
2
Syntax und Semantik
2.1 BNF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Semantik von Rekursion: Fixpunkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
8
8
3
Rekursion
3.1 Rekursionsarten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Korrektheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Terminierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
10
10
10
4
Imperative Programmierung
4.1 von-Neumann . . . . . .
4.2 Prozeduren . . . . . . .
4.3 Bindungen . . . . . . . .
4.4 Funktional vs. Imperativ
4.5 Parameterübergabe . . .
4.6 Hoare-Kalkül . . . . . .
.
.
.
.
.
.
11
11
11
11
11
11
12
Sortieralgorithmen
5.1 Selection Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Quick Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Heap Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
12
12
12
5
Informationssystem
1.1 Normalformsystem . . . . . . . . . . . .
1.2 Graphen . . . . . . . . . . . . . . . . . .
1.3 Transformationen . . . . . . . . . . . . .
1.4 Funktionale Programmierung . . . . . . .
1.5 Haskell . . . . . . . . . . . . . . . . . .
1.5.1 Deklarationen . . . . . . . . . . .
1.5.2 Basistypen und Typkonstruktoren
1.6 Vordefinierte Operationen . . . . . . . . .
1.7 Lokale Deklaration . . . . . . . . . . . .
1.8 Guards bzw If-Abfragen . . . . . . . . .
1.9 List Comprehension . . . . . . . . . . . .
1.10 Datentypen . . . . . . . . . . . . . . . .
1.11 Module . . . . . . . . . . . . . . . . . .
1.11.1 Sonstiges . . . . . . . . . . . . .
1.11.2 Wichtige Funktionen . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
Komplexität
6.1 Asymptotische Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 P/NP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
12
13
7
Formale Sprachen und Automaten
7.1 Allgemeines . . . . . . . . . . . . . .
7.2 Reguläre Sprachen . . . . . . . . . .
7.3 Kontextfreie Sprachen . . . . . . . .
7.4 Kontextsensitive und Typ 0-Sprachen
7.5 Überblick . . . . . . . . . . . . . . .
8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
14
16
17
18
Berechenbarkeit
8.1 Turing-Berechenbar . . . . . . . . . . . . . .
8.2 LOOP-Berechenbar . . . . . . . . . . . . . .
8.3 WHILE-Berechenbar . . . . . . . . . . . . .
8.4 GOTO-Berechenbar . . . . . . . . . . . . . .
8.5 Primitiv rekurisve und µ-rekurisve Funktionen
8.6 Die Ackermannfunktion . . . . . . . . . . .
8.7 Entscheidbarkeit,Halteproblem . . . . . . . .
8.8 Gödelsche Satz . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18
18
19
19
19
20
20
20
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1 Informationssystem
Eine Interpretation ist eine Zuordnung von Begriffen zu Bedeutungen (Semantik). Verschiedene Interpretation können derselben Repräsentation verschiedene Bedeutungen zuordnen. Zum Beispiel kann 1001 als
„eintausend-eins“ oder als 9 interpretiert werden.
Ein Informationssystem ist ein 3-Tupel (A, R, I). Hierbei ist A die Menge der Begriffe, R die Menge der
Repräsentationen und I eine Relation I : R → A mit r ∈ R 7→ I(r) = a wobei a die Bedeutung von r ist. I
nennen wir Interpretation.
Ein Informationssystem heißt
• mehrwertig wenn gilt (∃r : r ∈ R : |I(r)| > 1). Heißt also daß es für eine Repräsentation mehrere
Bedeutungen gibt. Zum Beispiel kann man mit Regen den Regen meinen der vom Himmel fällt :)
oder den Fluß Regen.
• mehrdeutig wenn gilt I(r) = I(s)mitr 6= s, also eine Bedeutung hat mehrere Repräsentationen. Zum
Beispiel kann man einen Verwandtschaftsgrad mit Opa oder Großvater bezeichnen. Die Bedutung
bleibt hierbei gleich.
1.1 Normalformsystem
Sei (A, R, I) ein Informationssystem und S ⊆ R eine ausgezeichnete Menge so nennen wir diese ein Normalformsystem. I|S ist dann die Standardinterpretation.
1.2 Graphen
Ein Graph ist ein 2-Tupel (V, E) wobei V die Menge der Knoten (engl. vertices) und E die Menge der
Kanten (engl. edges) darstellen. Es gilt E ⊆ V × V = {(u, v)|u, v ∈ V }. Für einen ungerichteten Graphen
gilt (u, v ∈ V ∧ (u, v) ∈ E ⇒ (v, u) ∈ E)
2
1.3 Transformationen
Eine Funktion fA heißt Äquivalenztransformation genau dann wenn
(∀r : r ∈ R : I(r) = I( fA (r)))
Eine Funktion fK heißt Kongruenztransformation genau dann wenn
(∀s, s′ : s, s′ ∈ R : I(s) = I(s′ ) ⇔ I( fK (s)) = I( fK (s′ )))
1.4 Funktionale Programmierung
Eine totale Funktion f : A → B erfüllt folgende Bedingung
(∀a : a ∈ A : (∃!b : b ∈ B : (a, b) ∈ f )
Die Substitutionsregel von Leibniz lautet
(∀x, y : x, y ∈ A : x = y ⇒ f (x) = f (y))
Darstellung einer Funktion f : A → B als λ-Ausdruck
f = (λa : a ∈ A : b)
wobei b die Rechenvorschrift für den Parameter a ist. Die Auswertung an einer bestimmten Stelle nennt
man hier Reduzierung.
Beispiel: (λx :: x ∗ x)2 = x ∗ x[2/x] = 2 ∗ 2 = 4
Die formalen Parameter eines Ausdrucks nennt man gebunden die anderen frei. Freie Parameter erhalten
ihre Werte aus der Umgebung.
Currying ist der Prozeß, aus einer Funktion mit zwei Parametern (etwa x, y) eine Funktion mit einem
Parameter x zu machen, die eine andere Prozedur mit einem Parameter y als Wert zurückgibt.
1.5 Haskell
1.5.1 Deklarationen
• Wertdeklaration
a :: Float
-- a ist vom Typ Float
a = 5.0 - 3.0 -- a erhält den Wert 2.0
• Funktionsdeklaration
double :: Float -> Float
double a = 2*a
-- Die Funktion geht von Float nach Float
-- Übergabeparameter a nehmen und 2*a zurückliefern
1.5.2 Basistypen und Typkonstruktoren
• Int Ganzzahlige endliche Werte
• Integer Wie Int nur unendlich
• Rationale Zahlen z.B. 1%2
3
• Float Gleitpunktzahl
• Double Höhere Genauigkeit als Float
• Bool Wahrheitswert
• Char Zeichen
• Strings Zeichenkette
• -> Funktion
• (.,.) karthesisches Produkt
• [] Liste
1.6 Vordefinierte Operationen
• Bool &&, not, ||
• Zahlen - (sowohl ein- als auch zweistellig), +, * , ’div’, ’mod’
• String ++ (Konkatenation)
• Listen [] (leere Liste]), a : [] (einfügen eines elements am Kopf)
1.7 Lokale Deklaration
Entweder mit let oder mit where
a :: Int
a = 2
let b = a*a
c = a+a
in b*c
a :: Int
a = 2
res = b*c
where b = a*a
c = a+a
1.8 Guards bzw If-Abfragen
summe :: Int -> Int
summe n = if n == 0 then 0
else summe (n-1) + n
summe :: Int -> Int
summe 0 = 0
summe n | n>0 = n + summe (n-1)
4
1.9 List Comprehension
[i*i | i <- [1..5]]
[x | let alphabet = "abcd", i <- alphabet, j <- alphabet, k <- alphabet,
let x=[i,j,k], x == reverse x]
1.10 Datentypen
• Enumerationstypen
data Season = Spring | Summer | Autumn | Winter deriving Show
deriving Show generiert automatisdch eine Ausgaberoutine
Gleichheit definieren
instance Eq Season where
Spring == Spring = True
...
_ == _ = False
Heißt das Season eine Instanz der Typklasse Eq ist und sozusagen
die Vergleichbarkeitseigenschaft besitzt. Automatisch ginge dies
auch mit ... deriving (Show, Eq)
• Produkttypen
data MyRational = Rat Int Int deriving (Show, Eq)
wird dann z.B. erstellt mit
Rat 2 3
Funktionen sehen z.B. so aus
num :: MyRational -> Int
num (Rat x y) = x
• Datentypen mit Varianten
data Currency = DM Double | Euro Double deriving (Show, Eq)
bedeutet dann daß
Euro 3 == DM 3
false liefert
Mit solchen Datentypen (z.B. data Mix = Set1 Int | Set 2 Bool) kann
man dann Listen des Typs Mix bilden, also Bool und Int gleichzeitig
in einer Liste speichern
• Polymorphe Datentypen
data Maybe a = Nothing | Just a
Nothing entspricht hierbei undefiniert/bottom
type IntMaype = Maybe Int
mit type werden nur Synonyme definiert
• Rekursive Datentypen
5
Stack:
data STACK a = EmptyStack | Push (a, STACK a)
BinärBaum:
data BTREE a = Notree | Node (BTREE a) a (BTREE a)
Beblätterter Baum:
date BBTREE a = BBLeaf a |
BBNode (BBTREE a) (BBTREEE a)
beliebiger Knotengrad
data NTREE a = NNode a [NTREE a] | NNoTree
type FOREST a = [ NTREE a ]
1.11 Module
module Name (exports...) where
.
.
.
Anstatt die einzelnen Konstruktoren aufzuzählen die exportiert werden sollen
kann man auch nur (...) für alles schreiben. In Programmen wird ein Modul
dann mit import "Dateiname.hs" eingebunden.
1.11.1 Sonstiges
• Haskell benutzt Typinferenz (type inference) d.h. es bestimmt den Typ jedes Ausdrucks selbst!
• Ein Paar <Name,Wert> heißt Bindung, eine Liste von Bindungen Umbebung. Die Auswertung
erfolgt mit sog. Formularen
• Eine Signatur Σ = (S, F) besteht aus einer Menge S von Typsymbolen und einer Menge F von
Funktionssymbolen. Die Rechnerstruktur einer Signatur Σ weist den Symbolen von Σ Bedeutungen
zu, S eine Trägermmenge und F Funktionen.
1.11.2 Wichtige Funktionen
ord :: Char -> Int -- ASCII-Code
chr :: Int -> Char -- Zeichen
abs :: Int -> Int
abs a | a < 0 = (-a)
abs a | a >= 0 = a
max :: Int -> Int -> Int
max a b | a < b = b
max a b | a >= b = a
min :: Int -> Int -> Int
min a b | a < b = a
min a b | a >= b = b
6
fac :: Int -> Int
fac 0
= 1
fac n | n>0 = n * fac(n-1)
rev :: [a] -> [a]
rev [] = []
rev (x:xs) = rev xs ++ [x]
map :: (a -> b) -> [a] -> [b]
map f []
= []
map f (x:xs) = (f x) : (map f xs)
zip
zip
zip
zip
:: [a]
[] _ =
- [] =
(a:as)
-> [b] -> [(a,b)]
[]
[]
(b:bs) = (a,b) : zip as bs
filter :: (a -> Bool) -> [a] -> [a]
filter p [] = []
filter p (x:xs) = if (p x) then x : (filter p xs)
else filter p xs
unzip :: [(a,b)] -> ([a],[b])
unzip [] = ([], [])
unzip ((a, b):rest) =
let (as, bs) = unzip rest
in (a:as, b:bs)
app :: [a] -> [a] -> [a]
app [] yl = yl
app (x:xs) yl = x : app xs yl
rev :: [a] -> [a]
rev [] = []
rev (x:xs) = rev xs ++ [x]
qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort (x:xs) = qsort [y | y<-xs, y<x] ++ [x] ++ qsort [y | y<-xs, y>x]
breadthsearch :: (a -> Bool) -> BTREE a -> Maybe a
breadthsearch p tree =
let searchForest [] = Nothing
searchForest (Notree : t) = searchForest t
searchForest (Node l x r : t) =
if p x then Just x
else searchForest (t ++ [l,r])
in searchForest[tree]
binarysearch :: (a -> a -> Bool) -> a -> BTREE a -> Maybe a
binarysearch less item Notree = Nothing
binarysearch less item (Node l x r) =
if less x item then binarysearch less item r
else if less item x
then binarysearch less item l
7
else Just x
2 Syntax und Semantik
2.1 BNF
Eine BNF-Grammatik G ist ein Quadrupel
G = (N, Σ, P, s)
wobei N eine Menge von Nichtterminalen, Σ eine Menge von Terminalen, P eine Menge von Produktionen,
und s ∈ N das Startsymbol ist. Mit BNF-Grammatiken können kontextfreie Sprachen beschrieben werden.
Kontextfrei heißen sie deshalb weil links in den Produktionen jeweils nur ein Nichtterminal steht.
Ein Ableitungsbaum ist ein Baum mit folgenden Eigenschaften
1. Alle Blätter sind Terminale
2. Alle inneren Knoten sind Nichtterminale
3. Die Wurzel ist daa Startsymbol
4. Die Nachfolger müssen durch Produktionen der Grammatik entstehen
Eine Grammatik heißt mehrdeutig wenn ein Wort mit mehreren Ableitungsbäumen hergeleitet werden
kann. Eine Sprache die sich nur durch mehrdeutige Grammatiken definieren läßt heißt auch mehrdeutig.
2.2 Semantik von Rekursion: Fixpunkte
Das Ergebnis rekursiver Funktionen kann in einer einzigen Funktion konzentriert werden. Gesucht ist also
eine Funktion q. Sie wird mittels des Fixpunkt-Funktionals approximiert, d.h. eine unzureichend genaue
Funktion wird an weiteren Punkten definiert. Mittels Funktions-Iteration wird das Funktional iteriert.
So wird systematisch der kleinste Fixpunkt der Funktion ermittelt. Es beginnt mit der überall-nichtdefinierten
Funktionen. Die Funktionen sind dabei nach der Approximationsordnung geordnet, letzlich also nach der
Anzahl definierter Funktionswerte. Die Menge der enstehenden Funktion ist eine Kette, d.h. alle Elemente
sind miteinander vergleichbar (die Nullfunktion ist kleiner als jede andere Funktion). Jeder Fixpunkt wird
dann unter dem Fixpunktfunktional auf sich selbst abgebildet (q = Q[q]). Das Supremum der Menge der q
wird kleinste Fixpunkt genannt. Dies ist die Funktion, die an den wenigsten Stellen festgelegt ist.
Eine Definition kann man als Gleichung ansehen. Die Bedeutung der Definition ist durch die Lösung(en)
der Gleichung gegeben
Man kann beispielsweise Funktionen folgendermaßen definieren:
q: → ⊥
q = (λn : n ∈ : i f n = 0 then 1 else q(n + 1))
Die Theorie zur Lösung dieser Gleichung heißt Fixpunkttheorie. Man versucht also eine Gleichung zu
finden die die Definition erfüllt. Hierfür wird q zu einem zusätzlichen Parameter und man erhält daß zugehörige
Fixpunktfunktional Q
Q : ( → ⊥) → ( → ⊥ )
N N
N
Q = (λq : q ∈
N N
N→N
⊥
N N
: (λn : n ∈
N : i f n = 0 then 1 else q(n + 1)))
Die Lösung der Gleichung sind dann alle Funktionen h die unter Q auf sich selbst abgebildet werden
Q[h] = h. Um eine Lösung zu finden muss
• mindestens ein Fixpunkt existieren
8
• wenn mehrere existieren, einer als Lösung ausgewählt werden
• die Lösung berechenbar sein
Wenn mehrere Fixpunkte existieren wird der kleinste Fixpunkt bzgl. der Approximationsordnung ausgewählt, in der eine Funktion f kleiner als eine Funktion g ist, wenn f mit g übereinstimmt aber unter
Umständen an weniger Punkten definiert ist.
Funktionsiteration
Eine Funktion f : M → N kann wie folgt iteriert werden:
(∀x : x ∈ M : f 0 (x) = x)
(∀x, i : x ∈ M ∧ i ∈ N ∧ i > 0 : f i (x) = f ( f i−1 (x)))
partielle Ordnung
Eine Relation ⊑⊆ M × M heißt partielle Ordnung gdw.:
(∀x : x ∈ M : x ⊑ x) (Reflexivität) (∀x, y : x, y ∈ M : x ⊑ y ∧ y ⊑ x ⇒ x = y) (Antisymetrie (∀x, y, z : x, y, z ∈
M : x ⊑ y ∧ y ⊑ z ⇒ x ⊑ z) (Transitivität)
Bottom
⊥ erfüllt folgende Eigenschaft (∀x : x ∈ M : ⊥ ⊑ x)
diskrete Ordnung
Wenn gilt x1 ⊑ x2 ⇔ x1 = ⊥ ∨ x1 = x2 dann heißt ⊑ diskrete Ordnung
Approximationsordnung
Sei ⊑ eine diskrete Ordnung auf M und seine f , g : M → N Funktionen dann ist die Relation
f ⊑ g ⇔ (∀x : x ∈ M : f (x) ⊑ g(x))
eine partielle Ordnung, die sog. Approximationsordnung.
gerichte Menge,obere Schranke,Supremum
Eine nichtleere Teilmenge X ⊆ M heißt gerichtet gdw.
(∀x, y : x, y ∈ X : (∃z : z ∈ X : x ⊑ z ∧ y ⊑ z))
z heißt dann obere Schranke von x und y. Als Supremum einer Menge bezeichnet man die kleinste obere
Schranke.
Funktionsmonotonie
Eine Funktion f : M → N ist monoton gdw.
x ⊑ y ⇒ f (x) ⊑ f (y)
bzw für ein Funktional τ
f ⊑ g ⇒ τ[ f ] ⊑ τ[g]
Stetigkeit
Eine Funktion f : M → N ist stetig gdw.
f (sup i : i ∈ N : xi ) = (sup i : i ∈ N : f (xi )
Fixpunktsatz
9
Ist τ eine stetige Abbildung üer einer vollständig geordneten Menge M mit kleinestem Element ⊥ so ist die
Gleichung
x = τ[x]
lösbar uns es existiert ein eindeutiger kleinster Fixpunkt.
3 Rekursion
3.1 Rekursionsarten
1. Lineare Rekursion tritt auf wenn bei der Deklaration der Funktion in jedem Zweig auftretender
Fallunterscheidungen der Funktionsaufruf maximal einmal auftritt.
2. Repetitive Rekursion ist ein Spezialfall der Linearen Rekursion. Hierbei erscheint in allen Funktionsaufrufen einer rekursiven Deklaration einer Funktion der rekursive Aufruf als letzte Aktion
3. Kaskadenartige Rekursion ist wenn in der Fallunterscheidung zwei oder mehrere Aufrufe der
Funktion stattfinden. (Divide and Conquer!!)
4. Vernestete Rekursion ist wenn in dem rekursiven Aufruf selbst wieder ein Rekursiver Aufruf auftritt. z.B.
ack
ack
ack
ack
:: Integral a => (a,a) -> a
(0,y) = y+1
(x,0) = ack(x-1,1)
(x,y) = ack (x-1, ack(x,y-1) -- Vernestet
5. Verschränkte Rekursion bedeutet daß in dem Aufruf von f nicht f vorkommt sondern eine Funktion g1 die dann eine Funktion g2 bis gn aufruft bis man letztendlich wieder bei f ist. Aus jeder
verschränkten Rekursion kann man mit Einführung eines zusätzlichen Paramaters eine direkte Rekursion machen.
3.2 Korrektheit
Sei f eine für alle x ∈ D definierte funktion und f ihre Implementation. f heißt.
• partiell korrekt, wenn
(∀x : x ∈ D : f(x) ist de f iniert ⇒ f (x) = f(x))
• total korrekt
(∀x : x ∈ D : f(x) ist de f iniert ∧ f (x) = f(x))
Partielle Korrektheit garantiert das spezifizierte Verhalten nur wenn man Termination vorraussetzt, totale
Korrektheit hingegen garantiert auch Termination. Aus partieller Korrektheit und Termination folgt deswegen totale Korrektheit.
3.3 Terminierung
Für den Beweis der Terminierung benötigt man eine Abstiegsfunktion. Sei für x ∈ M
f (x) = E[ f (E1 (x)), . . . , f (En (x))]
eine Funktionsdeklaration mit rekursiven Aufrufen f (E1 (x)), . . . , f (En (x)), wobei die Ei (x) keine rekursiven Aufrufe von f enthalten und sei für alle im Rumpf von f auftretenden Funktionen die Terminierung
bereits gezeigt. Sei Ci (x) die Bedingung unter der der rekursive Aufruf f (Ei (x)) erfolgt.
Die Terminierung von f auf M ist gesichert falls es eine Abbildung h : M → N gibt, so dass gilt:
(∀x, i : x ∈ M ∧ i ∈ {1, . . . , n} : Ci (x) ⇒ h(x) > h(Ei (x))
10
4 Imperative Programmierung
4.1 von-Neumann
Ein von-Neumann Rechner besitze einen linear organisierten Speicher mit wahlfreiem Zugriff (Random
Access), in dem Programme und Daten abgelegt werden. Die Abarbeitung von Programmen orientiert sich
daher am aktuellen Speicherzustand und bei jedem Arbeitsschritt werden Anweisungen ausgeführt die den
Zustand verändern. Deshalb heißt es imperative Programmierung.
4.2 Prozeduren
Als reine Prozedur bezeichnet man solche die an Stellen stehen, an denen ein Befehl erwartet wird. Hingegen stehen Funktionsprozeduren an Stellen an denen ein Ausdruck des Rückgabetyps wer Prozedur
erwartet wird. Man unterscheidet bei den übergebenen Parametern zwischen Eingabeparametern, Ausgabeparametern und eine Kombination von beiden, den transienten Parametern.
4.3 Bindungen
Bei statischer Bindung wird im Bereich der Prozedurdeklaration nach den Parametern gesucht, bei dynamischer Bindung hingegen in der Umgebung des Prozeduraufrufs.
4.4 Funktional vs. Imperativ
Im Funktionalen gibt es
• keine Programmvariablen
• keine Mehrfachzuweisung
• keine Schleifen (dafür Rekursion)
• keine Sprünge (goto)
• keine Zeiger
4.5 Parameterübergabe
Als L-Wert wird die Adresse einer Variable, als R-Wert deren Wert bezeichnet.
Call by Reference Der L-Wert des formalen Parameters wird auf den L-Wert des aktuellen Parameters
gesetzt.
Call by Name Bei einem Aufruf wird jedes Vorkommen des formalen Parameters durch den aktuellen
Parameter ersetzt. (siehe inline-Funktionen in C/C++)
Call by Value Der R-Wert des formalen Parameters wird auf den R-Wert des aktuellen Parameters gesetzt
Call by Result Der Rückgabewert wird in den L-Wert des aktuellen Parameters geschrieben, d.h. der RWert des aktuellen Parameters wird im Prozedurrumpf nicht genutzt.
Call by Value-Result Der R-Wert des aktuellen Parameters wird in den R-Wert des formalen Parameters
kopiert. Am Ende wird dann der R-Wert des formalen Parameters an die Stelle des R-Werts des
aktuellen Parameters kopiert.
11
4.6 Hoare-Kalkül
Die Regeln sind von der Form (Precondition) Programm (Postcondition). Um einen formelen Beweis für
ein Programm durchzuführen stellt man eine Precondition (Eingabe) auf und eine Postcondition (erwartete
Ausgabe). Nur geht man mit Hilfe des Kalküls durch die einzelnen atomaren Programmschritte und macht
aus der Precondition so die Postcondition. Da das Kalkül korrekt ist folgt nun auch die Korrektheit des
Vorraussetzung
.
Programms bzgl. der angegebenen Conditions. Die Kalkülregeln sind von der Form axiomatischerSchlu
Leere Anweisung
Zuweisung
{R[E/x]}x:=E{R}
Komposition
Auswahl
Schleife
true
{R}skip{R}
{P}S1 {Q};{Q}S2 {R}
{P}S1 ;S2 {R}
{P∧B}S1 {R},{P∧¬B}S2{R}
{P}i f B then S1 else S2 f i{R}
{I∧B}S{I},P⇒I,I∧¬B⇒R
{P}while B do S od{R}
Folgeregel
wobei I die Schleifeninvariante ist
P⇒P′ ,R′ ⇒R,{P′ }S{R′ }
{P}S{R}
5 Sortieralgorithmen
5.1 Selection Sort
Einfach immer das in der gegebenen Ordnung kleinste Element nach vorne ins Array holen und die Länge des zu betrachtenden Arrays verringern. Dies geschieht mit zwei For-Schleifen die maximal über die
Eingabelänge n laufen also O(n2 ) und Ω(n2 ).
5.2 Quick Sort
Die zu sortierende Folge a wird so in zwei Teilstücke b und c zerlegt, dass alle Elemente des ersten Stücks
b kleiner oder gleich allen Elementen des zweiten Stücks c sind (Divide). Danach werden die beiden Teilstücke sortiert, und zwar rekursiv nach demselben Verfahren (Conquer). Wieder zusammengesetzt ergeben
die Teilstücke die sortierte Folge (Combine). Im benötigt Quick Sort O(n log n)) da die Rekursionstiefe
log n ist und in jeder Schicht n Elemente zu behandeln sind. Im schlechtesten Fall der Eingabe allerdings
wie Bubble Sort O(n2 ).
5.3 Heap Sort
Ein Heap ist ein Binärbaum der vollständig ist und in der untersten Ebene gefüllt wird. Bei Einfügen eines
Elements am Ende wird heapify gemacht um die Heap-Eigenschaft wieder herzustellen. Hierfür wird das
eingefügte Element solange mit dem Vaterknoten verglichen bis keine Vertauschung mehr nötig ist. Intern
kann man einen Heap als Array repräsentieren mit Vater a[i] mit linker Sohn a[2i+1] bzw. rechter Sohn
a[2i+2]. Wenn man sortieren will erstellt man einen Heap und nimmt das oberste Element raus. Dann
das letzte Element im Array an die Position stellen und Heap-Eigenschaft wieder herstellen. Dann wieder
Wurzel rausnehmen usw. Die Komplexität ist selbst im schlechtesten Fall O(n log n) und somit optimal.
6 Komplexität
6.1 Asymptotische Notation
Mit O( f (n)) bezeichnen wir die Klasse aller Funktionen g mit der Eigenschaft
∃c > 0∃n0 > 0∀n ≥ n0 : g(n) ≤ c f (n)
12
Mit Ω( f (n)) bezeichnen wir die Klasse aller Funktionen g mit der Eigenschaft
∃c > 0∃n0 > 0∀n ≥ n0 : g(n) ≥ c f (n)
Mit Θ( f (n)) bezeichen wir die Klasse O( f (n)) ∩ Ω( f (n)).
6.2 P/NP
Die Klasse P sind alle Probleme A für die es eine deterministische Turingmaschine gibt die A in polynominialier Zeit löst.
Die Klasse NP sind alle Probleme A für die es eine nichtdeterministische Turingmaschine gibt die A in
polynominialier Zeit löst.
Seien A und B Probleme, dann heißt A auf B polynominail reduzierbar -symbolisch A ≤ p B- falls es
eine totale und mit polynominialer Komplexität berechenbare Funktion f gibt daß für alle Eingaben der
Probleme gilt
x ∈ A ⇔ f (x) ∈ B
Eine Problem heißt NP-hart falls sich alle Probleme aus NP auf dieses polynominial reduzieren lassen. Ein
Problem ist NP-vollständig falls es NP-hart ist und selbst in NP liegt.
SAT ist das Erfüllbarkeitsproblem der Aussagenlogik ob es für eine Formel F eine Belegung gibt dass
F wahr ist. SAT wurde als das NP-vollständige Problem gewählt. Die Idee die dahinter steckt ist, daß man
jedes Problem mit einem Algorithmus, also auch mit einer Turingmaschine darstellen kann. Man sucht nun
einen Algorithums mit polynominialer Komplexität um eine Turingmaschine als Aussagenlogische Formel
darzustellen die genau dann wahr ist wenn die Turingmaschine hält. Dies ist ja dann wieder das Problem
von SAT. Auf SAT führt man dann zunächst 3KNF-SAT zurück und auf dieses eine Vielzahl anderer Probleme wie TSP, Rucksack, Gerichteter Hamiltion Kreis.
7 Formale Sprachen und Automaten
7.1 Allgemeines
Eine Grammatik ist ein 4-Tupel G = (V, Σ, P, S) mit folgenden Bedingungen:
• V ist die endliche Menge der Variablen
• Σ ist eine endliche Menge von Terminalsymbolen
• Es gilt V ∩ Σ = 0/
• P ist eine endliche Menge von Produktionen der Form (V ∪ P)+ → (V ∪ P)∗ .
• S ist das Startsymbol
Die durch eine Grammatik G definierte Sprache L wird als L(G) = {w ∈ Σ∗ |S ⇒∗G w} dargestellt, wobei
⇒∗G bedeutet daß w durch beliebig viele Anwendung der Regeln von G aus S ableitbar ist.
Die Grammatiken wurden vom Linguisten Chomsky in eine Hierachie unterteilt mit folgenden Definitionen
• Zunächst ist jede Grammatik vom Typ0, sogenannte Phrasenstrukturgrammatiken
• Eine Grammatik ist von Typ1 bzw. kontextsensitiv, wenn ∀w1 , w2 ∈ P : w1 → w2 ⇒ |w1 | ≤ |w2 | gilt.
• Eine Typ1-Grammatik ist vom Typ2 bzw. kontextfrei, wenn ∀w1 , w2 ∈ P : w1 → w2 ⇒ w1 ∈ V gilt.
13
• Eine Typ2-Grammatik ist vom Typ3 bzw. regulär, wenn ∀w1 , w2 ∈ P : w1 → w2 ⇒ w2 ∈ Σ ∪ ΣV gilt.
Die von den jeweiligen Typ-Grammatiken erzeugten Sprachen werden dann Typ-[0-3]-Sprachen genannt.
Grammatiken nennen wir mehrdeutig wenn für ein Wort mehrere Syntaxbäume existieren.
Das Wortproblem für Typ1 Sprachen, also die Frage ob ein Wort x ∈ L(G) gibt, ist entscheidbar. Also
gibt es einen Algorithmus der bei Eingabe einer kontextsensitiven Grammatik G = (V, Σ, P, S) und eines
Wortes x ∈ Σ∗ in endlicher Zeit entscheidet ob x ∈ L(G) oder x ∈
/ L(G).
7.2 Reguläre Sprachen
Ein deterministischer endlicher Automat (kurz DEA) ist ein 5-Tuple M = (Z, Σ, δ, z0 , E) wobei
• Z eine endliche Menge von Zuständen
• Σ das endliche Eingabealphabet
• V ∩ Σ = 0/
• z0 ∈ Z Startzustand
• E ⊆ Z die Menge der Endzustände
• δ : Z × Σ → Z die Überführungsfunktion
ist. Zu einem gegebenen Automaten definieren wir eine Funktion δ̂ : Z × Σ∗ → Z induktiv durch
• δ̂(z, ε) = z
• δ̂(z, ax) = δ̂(δ(z, a), x)
Die von einem DEA Automaten dargestellte bzw. akzeptierte Sprache T (M) = {x ∈ Σ∗ |δ̂(z0 , x) ∈ E}
Jede durch einen endlichen Automaten erkennbare Sprache ist regulär!
Ein nichtdeterministischer endlicher Automat (kurz NEA) ist ein 5-Tuple M = (Z, Σ, δ, S, E) wobei
• Z eine endliche Menge von Zuständen
• Σ das endliche Eingabealphabet
• V ∩ Σ = 0/
• S ⊆ Z die Menge der Startzustände
• E ⊆ Z die Menge der Endzustände
• δ : Z × Σ → ℘(Z) die Überführungsfunktion
ist. Die Funktion δ kann wieder induktiv auf Wörter erweitert werden zu δ̂ : ℘(Z) × Σ∗ → ℘(Z) durch
• δ̂(Z ′ , ε) = Z ′ f uer alle Z ′ ⊆ Z
• δ̂(Z ′ , ax) =
S
z∈Z ′ δ̂(δ(z, a), x)
/
Die von einem NEA Automaten dargestellte bzw. akzeptierte Sprache T (M) = {x ∈ Σ∗ |δ̂(S, x) ∩ E 6= 0}
Jede durch einen NEA akzeptierte Sprache ist auch durch einen DEA akzeptierbar!
Sei ein NEA M = (Z, Σ, δ, S, E) gegeben so konstuieren wir durch die Potenzmengenkonstruktion einen
DEA M ′ = (Z ′ , Σ, δ′ , z0 , E ′ ) und zwar wie folgt.
14
• Z ′ = ℘(Z)
• z0 = S
/
• E ′ = {Y ⊆ Z|Y ∪ E 6= 0}
• δ′ (Y, a) =
S
y∈Y
δ(y, a) = δ̂(Y, a), Y ∈ Z ′
Für jede reguläre Grammatik G gibt es einen NFA M mit L(G) = T (M)!
Reguläre Ausdrücke sind spezielle Formen mit denen sprachen definiert werden können. Diese Ausdrücke
werden induktiv definiert und zwar
• 0/ ist ein regulärer Ausdruck
• ε ist ein regulärer Ausdruck
• ∀a ∈ Σ ist a ein regulärer Ausdruck
• wenn α und β reguläre Ausdrücke sind dann auch αβ, (α|β) und (α)∗ )
Die Semantik der regukären Ausdrücke sollte hinreichend bekannt sein.
Für jede reguläre Grammatik G gibt es einen NFA M mit L(G) = T (M)!
Um zu zeigen daß eine Sprache nicht regulär ist nutzt man das Pumping Lemma.
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, dass gilt
1. |v| ≥ 1
2. |uv| ≤ n
3. Fuer alle i = 0, 1, 2, . . . gilt uvi w ∈ L
Mit dem Pumping Lemma zeigt man durch Widerspruchsbeweis, daß eine Sprache nicht regulär ist.
Jeder Sprache L kann man einen Äquivalenzrelation RL auf Σ∗ zuordnen und zwar das gilt:
∀z ∈ Σ∗ : xz ∈ L ⇔ yz ∈ L
Eine Sprache L ist genau dann regulär, wenn der Index von RL endlich ist!
Der Automat der entsteht wenn man als Zustände die Äquivalenzklassen nutzt heißt Minimalautomat und
ist algorithmisch wie folgt konstruierbar:
• Eingabe ist ein DFA M und man erhält die Zustände die noch verschmelzbar sind
• Erstelle Tabelle von Zustandspaaren (z, z′ ) mit z 6= z′
• Markiere alla Paare die genau einen Terminalzustand enthalten
• Für jedes unmarkierte Paar (z, z′ ) und jedes a ∈ Sigma teste ob
(δ(z, a), δ(z, a′ ))
bereits markiert ist. Wenn ja markiere auch (z, z′ ).
• Wiederhole letzten Schritt bis sich keine Änderungen mehr ergeben
Die unmarkierten Paare können nun verschmolzen werden. Die Zeitkomplexität des Algorithmus liegt in
O(n2 )
15
7.3 Kontextfreie Sprachen
Eine kontextfreie Grammatik G mit ε ∈
/ L(G) heißt Chomsky Normalform falls alle Regeln eine der beiden
Formen haben
A → BC
A→a
Zu jeder kontextfreien Grammatik G mit ε ∈
/ L(G) gibt es eine Chomsky Normalform Grammatik G′ mit L(G) = L(G′ )
Eine kontextfreie Grammatik G mit ε ∈
/ L(G) heißt Greibach Normalform falls alle Regeln die Form
A → aB1 B2 . . . Bk (k ≥ 0)
Zu jeder kontextfreien Grammatik G mit ε ∈
/ L(G) gibt es eine Greibach Normalform Grammatik G′ mit
′
L(G) = L(G )
Das Pumping Lemma für kontextfreie Spachen verläuft in Analogie zu den regulären Sprachen.
Sei L eine kontextfreie Sprache. Dann gibt es eine Zahl n, so dass sich alle Wörter z ∈ L mit |z| ≥ n
zerlegen lassen in z = uvwxy, dass gilt
1. |vx| ≥ 1
2. |vwx| ≤ n
3. Fuer alle i = 0, 1, 2, . . . gilt uvi wxi y ∈ L
Mit Hilfe des Pumping Lemmas kann man verifizieren, daß eine kontextfreie Sprache über einen einelementigen Alphabet regulär ist.
Der Algorithmus für das Wortproblem hat exponentiellen Aufwand. Der CYK-Algorithmus der dieses Problem für kontextfreie Grammatiken entscheidet hat nur die Komplexität O(n3 )
1. Sei x die Eingabe und n = |x| dann erstelle eine Matrix n × n. Hierbei ist allerdings nur die obere
Diagonalhälfte interessant. Die Spalten der Matrix werden mit den einzelnen Buchstaben benannt.
2. In die erste Zeile trägt man für jeden Buchstaben alle Nichtterminale ein aus denen das Terminal
direkt abgeleitet werden kann.
3. Nun geht man Zeile für Zeile vor (Laufvariable j, erste For-Schleife)
4. Für jede Zeile geht man nun Spaltenweise durch (Laufvariable i, zweite For-Schleife)
5. Nun läßt man eine Variable k von 1 bis j-1 (dritte For-Schleife) laufen und trägt Nichtterminale in [j,i]
ein falls eine Regel der Form A → BC existiert mit der Eigenschaft daß B in [i,k] und C in [i+k,j-k]
steht.
6. Steht nun am Ende an der Stelle [n,1] das Startsymbol ist das Wort in der Sprache.
Durch die drei geschachtelten For-Schleifen erreicht man eine Zeitkomplexität von O(n3 ).
Ein nichtdeterministischer Kellerautomat (PDA) wird gegeben durch ein 6-Tupel M = (Z, Σ, Γ, δ, z0 , #)
mit
16
• Z die endliche Menge der Zustände
• Σ das Eingabealphabet
• Γ das Kelleralphabet
• z0 ∈ Z der Startzustand
• # ∈ Γ das unterste Kellerzeichen
• σ : Z × (Σ ∪ {ε}) × Γ → ℘e (Z × Γ∗ ) die Überführungsfunktion
Intuitiv bedeutet σ(z, a, A) ∋ (z′ , B1 . . . Bk ), daß wenn M sich im Zustand z befindet, a liest und A das oberste
Kellerzeichen ist so kann M in den Zustand z′ übergehen und das oberste Kellerzeichen A durch B1 . . . Bk
ersetzten (B1 ist dann oberstes Kellerzeichen). Sonderfälle entstehen wenn k = 0 (POP), Bk = A (PUSH)
und spontane Übergänge mit δ(z, ε, A).
Die von einem Kellerautomaten akzeptierte Sprache ist. N(M) = {x ∈ Σ∗ |(z0 , x, #) ⊢∗ (z, ε, ε) f uer ein z ∈
Z}.
Eine Sprache ist kontextfrei genau dann wenn sie von einem PDA erkannt wird!
Deterministische PDA spielen im Compilerbau eine große Rolle, da das Wortproblem in linearer Zeit lösbar
ist. Ein Beispiel für eine deterministisch kontextfreie Sprache ist L = {a1 . . . an $an . . . a1 |ai ∈ Σ}.
7.4 Kontextsensitive und Typ 0-Sprachen
Eine kontextsensitive Grammatik G mit ε ∈
/ L(G) heißt Kuroda Normalform falls alle Regeln eine der
Formen haben
A→a
A→B
A → BC
AB → CD
Für jede kontextsensitive Grammatik G mit ε ∈
/ L(G) gibt es eine Grammatik G′ in Kuroda Normal′
form mit L(G) = L(G )
Eine Turingmaschine (TM) ist gegeben durch ein 7-Tupel M = (Z, Σ, Γ, δ, z0 , ⋄, E). Hierbei sind
• Z die endliche Zustandsmenge
• Σ das Eingabealphabet
• Γ ⊃ Σ das Arbeitsalphabet
• z0 ∈ Z der Startzustand
• ⋄ ∈ Γ − Σ das Blank
• E ⊆ Z die Menge der Endzustände
• δ : Z × Γ → Z × Γ × {L, N, R} im deterministischen Fall bzw. δ : Z × Γ → ℘(Z × Γ × {L, N, R}) im
nichtdeterministischen Fall die Überführungsfunktion
17
Die von einer Turingmaschine M akzeptierte Sprache ist T (M) = {x ∈ Σ∗ |z0 x ⊢∗ αzβ; α, β ∈ Γ∗ ; z ∈ E}
Durch TM erkennbare Sprachen sind genau die Typ 0-Sprachen!
Eine Linear Beschränkte Turingmaschine (LBA) unterscheidet sich nur dadurch von einer TM, daß sie
den Bandbereich auf den die Eingabe steht nie verläßt. Hierfür muß noch ein Ende-Symbol eingeführt werden. Dafür verdoppelt man das Eingabealphabet Σ zu Σ′ = Σ ∪ {â|ßnΣ}. Die Eingabe a1 a2 . . . an−1 an wird
dann als a1 a2 . . . an−1aˆn aufs Band geschrieben. Es gilt also für eine LBA für alle a1 a2 . . . an−1 an ∈ Σ+ und
alle Konfigurationen αzβ mit z0 a1 a2 . . . an−1 aˆn ⊢∗ αzβ daß |αβ| = n.
Die von einer LBA akzeptierte Sprache ist T (M) = {a1 a2 . . . an−1 an ∈ Σ∗ |z0 a1 a2 . . . an−1 aˆn ⊢∗ αzβ; α, β ∈
Γ∗ ; z ∈ E}
Die von linear beschränkten nichtdeterministischen Turingmaschinen akzeptierten Sprachen sind
genau die kontextsensitiven!
7.5 Überblick
Beschreibungsmittel
Typ 3 reguläre Grammatiken, NFA, DFA, regulärer Ausdruck
Typ 2 kontextfreie Grammatiken, PDA
Typ 1 kontextsensitive Grammatiken, LBA
Typ 0 Typ 0-Grammatiken, TM
Abschlußeigenschaften
Schnitt Vereinigung Komplement Produkt Stern
Typ 3
ja
ja
ja
ja
ja
Typ 2
nein
ja
nein
ja
ja
Typ 1
ja
ja
ja
ja
ja
Typ 0
ja
ja
nein
ja
ja
Wortproblem
Typ 3 lineare Komplexität (Zeichen für Zeichen vergleichen)
Typ 2 O(n3 ) CYK
Typ 1 exponentielle Komplexität, NP-vollständig
Typ 0 unlösbar
8 Berechenbarkeit
Churchsche These:
Die durch die formale Definition der Turing-Berechenbarkeit erfasste Klasse von Funktionen stimmt
genau mit der Klasse der im intuitiven Sinn berechenbaren Funktionen überein
8.1 Turing-Berechenbar
N
N
Eine Funktion f : k → heißt Turing-berechenbar, falls es eine deterministische Turingmaschine M
gibt, so daß für alle n1 . . . nk , m ∈ gilt
N
f (n1, . . . , nk ) = m ⇔ z0 bin(n1 )#bin(n2)# . . . #bin(nk ) ⊢∗ ⋄ . . . ⋄ ze bin(m) ⋄ . . .⋄
wobei ze ∈ E. Eine Funktion f : Σ∗ → Σ∗ heißt Turing-berechenbar, falls es deine deterministische Turingmaschine M gibt, so dass für alle x, y ∈ Σ∗ gilt
f (x) = y ⇔ z0 x ⊢∗ ⋄ . . . ⋄ ze y ⋄ . . .⋄
wobei ze ∈ E.
18
8.2 LOOP-Berechenbar
Ein LOOP-Programm ist aus folgenden Komponenten aufgebaut
• Variablen x0 , x1 . . .
• Konstanten 1, 2 . . .
• Trennsymbole ; :=
• Operationszeichen + • Schlüsselwörter LOOP DO END
Jede Wertzuweisung der Form xi := x j + c bzw. xi := x j − c ist ein LOOP-Programm.
Falls P1 und P2 bereits LOOP-Programme sind dann auch P1 ; P2 .
Falls P ein LOOP-Programm und xi eine Variable dann ist auch LOOP xi DO P END ein LOOP-Programm.
Die Semantik ist offensichtlich. Anzumerken ist nur daß bei der Ausführung des LOOP schon vorher feststeht wie oft dies geschieht. Das LOOP-Programm P hat also keinen Einfluß auf die Anzahl der Durchläufe.
N
N
Eine Funktion f : k → heißt LOOP-berechenbar, falls es ein LOOP-Programm P gibt, daß f in dem
Sinne berechnet, dass P, gestartet mit n1 . . . nk in den Variablen x1 . . . xk (0 im Rest) stoppt mit dem Wert
f (n1 . . . nk ) in x0 .
8.3 WHILE-Berechenbar
WHILE erweitert LOOP um folgendes Konzept:
Falls P ein WHILE-Programm und xi eine Variable, dann ist auch W HILE xi 6= 0 DO P END ein WHILEProgramm.
N
N
Eine Funktion f : k → heißt WHILE-berechenbar, falls es ein WHILE-Programm P gibt, daß f in
dem Sinne berechnet, dass P, gestartet mit n1 . . . nk in den Variablen x1 . . . xk (0 im Rest) stoppt mit dem
Wert f (n1 . . . nk ) in x0 .
Da man WHILE-Schleifen auf Mehrband-Turingmaschinen simulieren kann (i-tes Band = i-te Variable)
und man jede Mehrband-Turingmaschine durch eine Ein-Band-Turingmaschine darstellen kann ist offensichtlich daß gilt:
Turingmaschinen können WHILE-Programme simulieren. D.h. jede WHILE-Berechenbare Funktion ist auch Turing-berechenbar
8.4 GOTO-Berechenbar
Ein GOTO-Programm ist aus folgenden Komponenten aufgebaut
• Variablen x0 , x1 . . .
• Konstanten 1, 2 . . .
• Trennsymbole ; :=
• Operationszeichen + • Schlüsselwörter GOTO IF THEN HALT
Wobei das Programm aus Sequenzen von Anweisungen Ai besteht die jeweils von einer Marke Mi eingeleitet werden. Als mögliche Anweisungen sind zugelassen
• Zuweisung xi := x j ± c
19
• unbedingter Sprung GOT O Mi
• bedingter Sprung IF xi = c T HEN GOT O Mi
• Stopanweisung HALT
Es gilt:
GOTO-Berechenbar ⇔ Turing-berechenbar ⇔ WHILE-Berechenbar
8.5 Primitiv rekurisve und µ-rekurisve Funktionen
Die Klasse der primitiv rekursiven Funktionen ist induktiv definiert
1. Alle konstanten Funktionen sind primitiv rekursiv
2. Alle identischen Abbildungen sind primitiv rekursiv
3. Die Nachfolgerfunktion sind primitiv rekursiv
4. Jede Funktion die durch Komposition von primitiv rekursiven Funktionen entsteht ist primitiv rekursiv
5. Jede Funktion dir durch so genannte primitive Rekursion entsteht ist sind primitiv rekursiv. Primitive
Rekursion bedeutet daß die Definition von f (n + 1 . . . zurückgeführt wird auf f (n . . .). Formaler muß
f folgendes Gleichungssystem erfüllen
f (0, . . .) = g(. . .) und f (n + 1, . . .) = h( f (n, . . .), . . .)
wobei h, g bereits primitiv rekursiv ist.
Die Klasse der primitiv rekursiven Funktionen stimmt mit derer der LOOP-Berechenbaren überein!
Sei f eine gegebene k + 1-stellige Funktion. Die Durch Anwendung des µ − Operators auf f enstehende Funktion ist g : k → mit
N
N
g(x1 , . . . , xk ) = min{n| f (n, x1 , . . . , xk ) = 0 und f ue; alle m < n ist (m, x1 , . . . , xk ) de f iniert}
Die Klasse der µ-rekursiven Funktionen stimmt mit der der WHILE-Berechenbaren überein!
8.6 Die Ackermannfunktion
Die Achkermannfunktion
a(0, y) = y + 1
a(x, 0 = a(x − 1, 1), x > 0
a(x, y) = a(x − 1, a(x, y − 1)), x, y > 0
ist nicht LOOP-berechenbar aber WHILE-berechenbar. Es gibt als totale Funktionen die WHILE aber nicht
LOOP-berechenbar sind.
8.7 Entscheidbarkeit,Halteproblem
Eine Menge A ⊆ Σ∗ heißt entscheidbar, falls die charakteristische Funktion von A, nämlich χA : Σ∗ →
{0, 1}, berechenbar ist. Hierbei ist für alle w ∈ Σ∗ :
(
1, w ∈ A
χA (w) =
0, w ∈
/A
20
Eine Menge A ⊆ Σ∗ heißt semi-entscheidbar, falls die charakteristische Funktion von A, nämlich χA : Σ∗ →
{0, 1}, berechenbar ist. Hierbei ist für alle w ∈ Σ∗ :
(
1,
w∈A
χA (w) =
unde f iniert, w ∈
/A
Eine Sprache A ist entscheidbar wenn sowohl A als auch das Komplement semi-entscheidbar sind!
Eine Sprache A ⊆ Σ∗ heißt rekursiv aufzählbar, falls A = 0/ oder falls es eine totale und berechenbare
Funktion f : → Σ∗ gibt, so dass
A = { f (0), f (1), . . .}
N
Man sagt daß f A aufzählt. Der unterschied zur einfachen Aufzählbarkeit ist, daß hier die Berechenbarkeit
verlangt wird.
Eins Sprache ist rekursiv aufzählbar gdw. sie semi-entscheidbar ist!
(
M,
f alls w Codewort von M
Sei Mw =
. Unter dem speziellen Halteproblem versteht man die SpraM̂sonst
che
K = {w ∈ {0, 1}∗ |Mw angesetzt au f w hlt}
Das spezielle, das allgemeine und das Halteproblem auf leerem Band sind nicht entscheidbar
8.8 Gödelsche Satz
Die Menge der wahren Arithmetischen Formeln ist nicht rekursiv aufzählbar
Jedes Beweissystem für die Menge der wahren arithmetischen Formeln ist unvollständig, d.h. es
bleiben immer formeln übrig die nicht beweisbar sind!
21
Herunterladen