Kapitel 4 Berechenbarkeit

Werbung
Kapitel 4
Theoretische Informatik 1
28. Januar 2003
Berechenbarkeit
1
Fahrplan
2
1.1.2 Turing-Maschinen
Turings Vorstellung von Algorithmen:
-werden ausgeführt mit Bleistift, Radiergummi und (in
unbegrenzten Mengen vorhandenem) Papier.
4.1 Präzisierung des Algorithmenbegriffs
-Papier ist unterteilt in Felder (z.B. Karos). In jedem Karo steht
ein Symbol (anfangs das “leere Symbol”)
4.2 Die Unentscheidbarkeit des Halteproblems
4.3 Die Beweismethode Diagonalisierung
-Schritt: Ein bestimmtes Karo auswählen und lesen und/
oder schreiben
4.4 Weitere unentscheidbare Probleme
4.5 Die Unentscheidbarkeit der Erfüllbarkeit in der
Prädikatenlogik
3
Turing-Maschine: Beispiel
δ
X = {|,$,*}
(* = Leerzeichen)
Z = {z0,...,z4}
z0
*
|
z0
|
z0
*
Erläuterung
|
*
$
z1, $, R
z0, *, S
z0, $, S
Starte
Iteration
z1
z1, |, R
z2, *, R
z0, $, S
nach R
bis zu *
z2
z2, |, R
z3, |, R
z0, $, S
nach R,
+ ein |
z3
z3, | , S
z4, |, L
z0, |, S
ein weit.
|
z4
z4, |, L
z4, *, L
z0, |, R
zurück
zum $
*
*
*
*
*
-lesen: Abhängig vom Symbol im ausgewählten Karo eine
Entscheidung treffen (z.B. welcher Schritt als nächstes
auszuführen ist)
-schreiben (das Symbol am ausgewählten Karo wegradieren und
4
durch ein neues ersetzen)
Turing-Berechenbarkeit
Eine n-stellige zahlentheoretische Funktion heißt
Turing-berechenbar, falls es eine Turing-Maschine M gibt,
die,
gestartet auf einer Konfiguration
* * | | ... | * | | ... | * ... * | | ... | * * * * * * *
x2+1
xn+1 z0
x1+1
-nicht terminiert, falls [x1,...,xn] Df
-in der Konfiguration
* * | |
*
5
| * | |
| *
* | |
| * | |
| * *
x2+1
x1+1
xn+1 f(x1,...xn)+1
terminiert, falls [x1,...,xn] ∈ Df
6
1
Partiell-rekursive Funktionen
Die Church-sche These
Anfangsfunktionen N, Cij, Iij
Substitution
φ1,...,φn m-stellig
ψ n-stellig
intuitiv-anschaulich
berechenbar
Der heikle Punkt der
Churchschen These
χ m-stellig
χ(x1,...,xm) := ψ(φ1(x1,...,xm),...,φn(x1,...xm))
offensichtlich
partiellTuring= rekursiv
berechenbar
=
Formaler
Begriff 3
Primitive Rekursion
φ n-stellig
χ (n+1)-stellig
ψ(n+2)-stellig
=
.........
beweisbar
7
Jenseits von primitiv rekursiv...
χ(x1,...,xn,0) = φ(x1,....,xn)
χ(x1,...,xn,i+1) = ψ(x1,...,xn,i,χ(x1,...,xn,i))
“primitiv-rekursive Funktionen”
Finally: Der dritte Induktionsschritt
Es gibt intuitiv-anschaulich berechenbare Funktionen,
die nicht primitiv rekursiv sind:
µ-Rekursion
z.B. die von R. Peter als nicht primitiv rekursiv nachgewiesene
totale Funktion
Falls φ eine (n+1)-stellige partiell-rekursive
Funktion ist,so ist die n-stellige Funktion ψ,
die wie folgt definiert ist, partiell rekursiv
peter(0,n) = n+1
peter(m+1,0) = peter(m,1)
peter(m+1,n+1) = peter(m,peter(m+1,n))
peter(0,n) = n+1
peter(1,n) = n+2
peter(2,n) = 2n+3
peter(3,n) = 2n-3-3
peter(4,0) = 13 peter(4,1) = 65536 peter(4,2)=265536-3
8
ψ(x1,...,xn) ist
- das kleinste j mit φ(x1,...,xn,j) = 0,
falls
- ein solches j existiert und
- für alle k<j die Werte φ(x1,...,xn,k)
definiert sind,
- nicht definiert, sonst.
Einige Werte:
9
psi(x1,...,xn){
y=0;
while(phi(x1,...,xn,y) != 0) {
y++; }
return y; }
Schreibweise: ψ(x1,...,xn) = µj[φ(x1,...,xn,j)=0]
10
Allgemein
Beispiel
Die Menge der partiell-rekursiven Funktionen entspricht
genau den Funktionen, die sich in “normalen” Programmiersprachen mit
-Zuweisung (Expressions mit +,-,*,DIV,MOD)
-Sequenz (...;...)
-if-then-else
-Zählschleifen (for ...)
-while-Schleifen und/oder Rekursion
implementieren lassen
Sei f(x,y) = 7 –• x • y
und g(x) = µj[f(x,j)=0]
Dann ist
g(1) = 7, weil f(1,0)=7, f(1,1)=6,...,f(1,6)=1, f(1,7)=0
g(2) = 4, weil f(2,0)=7, f(2,1)=5, f(2,2)= 3, f(2,3)=1, f(2,4)=0
g(200) = 1, weil f(200,0)=7, f(200,1) = 0
g(0) nicht definiert, weil f(0,0)=7, f(0,1)=7, ...., f(0,i)=7,....
11
µ-Rekursion kann aus einer totalen Funktion eine
partielle, nicht totale Funktion generieren, aber auch aus einer
partiellen, nicht totalen Funktion eine totale.
Alle partiell-rekursiven Funktionen sind int.-ansch. berechenbar
12
(Beweis: mitgelieferte Code-Fragmente).
2
Zur Äquivalenz formaler
Berechenbarkeitsbegriffe
Bezeichnungen und Inklusionen
ANF – Menge der Anfangsfunktionen
PRIM – Menge der primitiv-rekursiven Funktionen
PREK – Menge der partiell-rekursiven Funktionen
REK – Menge der (Allgemein-)rekursiven Funktionen
= Menge der totalen partiell-rekursiven Funktionen
Wollen jetzt, um die Church-sche These zu erhellen,
uns Ideen des Beweises der Äquivalenz zweier formaler
Berechnbarkeitsbegriffe erarbeiten.
Satz:
Eine zahlentheoretische Funktion ist Turing-berechenbar
genau dann, wenn sie partiell-rekursiv ist.
ANF
Addition
PRIM
REK
peter
PREK
Beweis Teil 1: Jede partiell-rekursive Funktion ist
Turing-berechenbar
die nirgends def.
Funktion
Beweis Teil 2: Jede Turing-berechenbare Funktion ist
partiell-rekursiv
13
Jede partiell-rekursive Funktion ist
Turing-berechenbar
14
mit Turing-Maschinen geht’s genauso
Eine analoge Aussage wäre: Jede partiell-rekursive
Funktion ist Pseudocode-berechenbar:
Nachfolger: Argument kopieren (das Verdoppelungsbeispiel
zeigt die Idee, wie), dann einen Strich anhängen, fertig.
Beweis durch Induktion
Induktionsanfang:
Induktionsschritt:
Konstanten: Einfach j Striche generieren
N(x) {
y = x+1;
return y;}
Cij(x1,..,xi){
return j;}
Iij(x1,..,xi){
return xj;}
chi(x1,....,xm) {
y1 = phi_1(x1,..,xm);
...
yn = phi_n(x1,..,xm);
z = psi(y1,...,yn);
return z; }
chi(x1,...,xn,i) {
y = phi(x1,...,xn);
for(j=0;j<i;j++) {
y = psi(x1,...,xn,j,y);}
return y; }
psi(x1,...,xn){
y=0;
while(phi(x1,...,xn,y) != 0) {
y++; }
return y; }
15
mit Turing-Maschinen geht’s genauso
Für die Induktionsschritte braucht man “Unterprogrammrufe”.
Das geht wegen folgender Beobachtung:
Wenn f T.-berechenbar ist, dann gibt es auch eine T.-Maschine,
die f berechnet und dabei nie den Kopf um mehr als 1 nach links
über die Argumente hinausfährt (“normierte” T.-Maschine)
Idee: Anfang und Ende des “Arbeitsbereiches” durch spezielle
Symbole “A” und “E” kennzeichnen.
- Kopf auf “E”: “E” eins nach rechts verschieben, ein * an die
alte Position, fortsetzen wie bisher
- Kopf auf “A”: den gesamten Arbeitsbereich um 1 nach rechts
kopieren, an die alte Position ein *, weiter wie vorgesehen
Unterprogrammrufe: Argumente ans rechte Ende kopieren,
Sprung zum Anfangszst. der Unterprogrammmaschine,
17
statt STOP Rücksprung ins Hauptprogramm
Argumentauswahl: Das richtige Argument kopieren:
man muss lediglich “mitzählen”, über wieviele “*” der Kopf
bewegt werden muss, um zur richtigen Strichfolge zu gelangen.
Das erreicht man über Wechsel von Zuständen:
|
*
z1 [z1,|,R] [z2,*,R]
z2 [z2,|,R] [z3,*,R]
z3 [z3,|,R] [z4,*,R]
16
z4 ....
Jede Turing-berechenbare
Funktion ist partiell rekursiv
Ebenfalls eine ideenspendende Analogie:
Jede Turing-berechenbare Funktion ist Pseudocode-berechenbar
f(x1,...,xn)
- Anfangskonfiguration aufs Band schreiben z := z0; /* band und kopf sind vorgegeben */
while true do
x := band[kopf]; [z’,x’,b] := δ(z,x); band[kopf] := x’;
switch(b) of
case N: skip;
case L: kopf := kopf – 1;
case R: kopf := kopf + 1;
case S: exit;
end
z := z’;
end
- Resultatstriche der Endkonfiguration zählen –
return result;
18
3
Mit PREK geht’s genauso, nur:
Gödelisierung
Hauptschwierigkeit:
Partiell-rekursive Funktionen haben keine strukturierten
Datenstrukturen!
Zunächst: eine nat. Zahl für “kopf” reicht, wg. Überlegungen
zu normierten Turing-Maschinen
Z und X können ebenfalls mit nat. Zahlen dargestellt werden
S
zi
0
i
L
X = {x1,...,xn} xj
*
0 |
1
N
2 R
3
1
j
19
Die Gödelzahl einer Turing-Maschine
... ist die Gödelisierung ihrer Zustandsüberführungsfunktion δ:
Schritt 1: einen Tabelleneintrag [z’,x’,b] gödelisieren
Schritt 2: Eine Tabellenzeile gödelisieren
Schritt 3: Die Tabellenspalten gödelisieren
δ
gö(
|
*
z0
z1,$,R z0, *, S z0, $, S
z1
z1, |, R z2, *, R z0, $, S
z2
z2, |, R z3, |, R
z3
z3, | , S z4, |, L
z4
(*
z4, |, L z4, *, L
0, |
1, $
2)
23
21•31•53
22•30•53
x3 x8
x2
x0
x2 x0
x0
0
2
2
5
3
7
4 5
11 13
6
17 ....
1
3
gö([x3,x8,x2,x0,x2,x0,x0,...]) = 23•38•52•70•112•130•170•...
Nehmen 0 als Code für das Leerzeichen,
dann hat jede für Turing-Berechenbarkeit
relevante Bandbeschriftung einen
wohldefinierten Code.
20•32•50
•2
•5
•33
) = 322•31•53•223•31•53•520•32•50
z0, $, S
•5
23•31•50•224•31•51•520•31•50
z0, |, S
•73
z0, |, R
24•31•51•224•30•51•520•31•53
•113
21
Der Kleene-sche Darstellungssatz
Eine Zusammenfassung der Implementation Turingberechenbarer Funktionen durch partiell-rekursive Funktionen
Satz: Es gibt eine primitiv-rekursive Funktion α, so daß
zu jeder Stellenzahl n
eine primitiv-rekursive n+2-stellige Funktion β existiert,
so daß zu jeder Turing-berechenbaren Funktion f
eine Zahl t existiert,
so daß für alle nat. Zahlen x1,....,xn gilt
f(x1,....,xn) = α( µj( β(t,x1,...,xn,j) = 0) )
α n β f t x1... xn
20
Zugriff auf Komponenten
gödelisierter Daten
Beide Funktionen sind primitiv-rekursiv (d.h. man braucht
in “normalen” Sprachen nur for- aber keine while-Schleifen):
For-Schleifen reichen für p, weil p(n+1) zwischen p(n)+1
und p(n)!+1 liegen muss, und ein Primzahltest für z über
Restberechnungen bei Division duch 2 ... z-1 implementiert
werden kann.
For-Schleifen reichen für exp, weil z nicht mehr als z mal
durch die n-te Primzahl ohne Rest dividierbar ist.
22
α n β f t x1... xn
µj(β
β(t,x1,...,xn,j)=0)
f(x1,...,xn) = α(µ
gö([z23,x45,L]) = 223•345•51
[23,45,1]
Brauchen: 1. p(n) = die n-te Primzahl
2. exp(n,z) = der Exponent der n-ten Primzahl in z
21•32•53•220•30•50•520•32•50
$
[z23,x45,L]
(leer, wg,
normiert)
Wie implementiert man also band[...], δ[z,x], [z’,x’,b]?
Z = {z1,...,zm}
= Kodierung komplexer Daten als einfache nat.
Zahlen, basierend auf Eindeutigkeit der Primzahlzerlegung
23
f(x1,...,xn)
var kopf, band, z,z’,x,x’,b;
- Anfangskonfiguration x1,....,xn aufs Band schreiben z := z0;
while true do
x := band[kopf]; [z’,x’,b] := δ(z,x); band[kopf] := x’;
switch(b) of
case N: skip;
case L: kopf := kopf – 1;
case R: kopf := kopf + 1;
case S: exit;
end
z := z’;
end
- Resultatstriche der Endkonfiguration zählen –
return result;
24
4
Konsequenzen aus dem Kleeneschen Darstellungssatz
Universelle Turing-Maschinen
α n β f t x1... xn f(x1,....,xn) = α( µj( β(t,x1,...,xn,j) = 0) )
1. (unwichtig, aber lustig): Jede berechenbare Funktion
kann so programmiert werden, daß nur eine einzige
while-Schleife verwendet wird, ansonsten nur
for-Schleifen, Zuweisungen und if-then-elses.
Spezialfall für n=1:
α β f t x f(x) = α( µj( β(t,x,j) = 0) )
2. (wichtig) Jede Turing-berechenbare Funkion ist
partiell-rekursiv; dies ist eine wichtige Erhärtung der
Church-schen These
Also:
A f t x f(x) = A(t,x)
3. (wichtig; hier spielt die Quantorenreihenfolge eine
entscheidende Rolle) Es gibt sogenannte “universelle”
Turing-Maschinen, das sind Maschinen, die die Arbeit
jeder beliebigen Turing-Maschine nachvollziehen 25
können
Veranschaulichung 1
0
1
2
3
4
5
6
0
0
3
n.d. 3
0
2
910 222 42
1
2
3
5
7
11
13
17
19
23
2
0
0
0
0
0
0
0
0
0
3
1
2
3
4
5
6
7
8
9
4
n.d n.d n.d n.d n.d n.d n.d n.d n.d
5
1
4
6
7
n.d. 7
7
111 939 933 382 281 810 n.d. 729 1
8
900 100 200 300 400 929 039 930 291
16
25
n.d. 7
36
49
n.d. 7
64
Setzen A(t,x) = α( µj( β(t,x,j) = 0) )
Interpretiert: Es gibt eine 2-stellige Turing-berechenbare
Funktion A, so daß der Wert jeder einstelligen Turing-berechenbaren Funktion f an jeder beliebigen Stelle x dadurch berechnet
werden kann, daß A an der Stelle t und x berechnet wird, wobei t
die Gödelzahl einer f berechnenden Turing-Maschine ist. 26
Veranschaulichung 2
A
9
7
8
Programm als
t
Zahl (ASCII statt
Gödelisierung)
81
n.d. 7
C10
x
Daten
A
die nirgends definierte Funktion
f(x) = (x+1)2
27
....jede einstellige berechenbare Funktion taucht als Zeile in A auf!
Ein Rechner, der alle Progamme abarbeiten kann
28
4.2 Die Unentscheidbarkeit
des Halteproblems
Bemerkung
Ausgangspunkt: Eine universelle TM A.
Es gibt sogar eine universelle Turing-Maschine, mit der sich
alle Funktionen beliebiger Stelligkeit simulieren lassen.
Einziger Trick:
Das Halteproblem:
Entscheide die Menge derjenigen geordneten Paare
[t,x], für die A(t,x) definiert ist
Mehrstellige Argumenttupel zu einem Argument
“zusammengödelisieren”
(oder, informaler: Entscheide, ob eine gegebene
Turing-Maschine bei gegebener Eingabe terminiert)
Wir zeigen durch einen Widerspruchsbeweis, daß das
Halteproblem nicht entscheidbar ist, also die Funktion
1, falls A(t,x) definiert
h(t,x) =
0, falls A(t,x) nicht definiert, nicht berechenbar ist.
29
30
5
Angenommen, h wäre berechenbar,...
dann wäre sicherlich auch die einstellige Funktion g mit
0, falls A(x,x) nicht definiert
g(x) =
A(x,x) + 1, falls A(x,x) definiert, berechenbar:
g(x) = if h(x,x) > 0 then A(xx) + 1 else 0. g wäre also total.
Wenn nun g berechenbar wäre, müsste g irgendwo als Zeile
in A auftauchen, es gäbe also ein tg so, daß für alle x
g(x) = A(tg,x) ist. Nun ist aber
A(tg,tg)
=
g(tg) =
A(tg,tg) + 1, Widerpruch!
31
(weil Zeile tg von A g repr.) (nach Def. von g)
Veranschaulichung
A
0
1
2
3
4
5
6
0
0
3
n.d. 3
0
2
910 222 42
1
2
3
5
7
11
13
17
19
23
2
0
0
0
0
0
0
0
0
0
3
1
2
3
4
5
6
7
8
9
4
5
n.d. n.d. n.d. n.d. n.d n.d. n.d. n.d. n.d.
.
1
4
9
16 25
36 49 64 81
6
7
7
111 939 933 382 281 810 n.d. 729 1
8
900 100 200 300 400 929 039 930 291
tg
1
n.d. 7
4
1
n.d. 7
5
0
n.d. 7
37
8
7
8
tg
n.d. 7
730 292
Wid
32
6
Herunterladen