Sie sind auf Seite 1von 27

Rekursive Funktionen

Christoph Kreitz
Institut f ur Informatik, Universit at Potsdam, 14482 Potsdam
Dieser Artikel ist noch nicht ganz fertig und enthalt vor allem noch Tippfehler und kleine-
re Unsauberkeiten. Er wird im Laufe der nachsten Wochen durch eine leicht uberarbeitete
Version ersetzt.
Zusammenfassung Dieser Artikel gibt einen

Uberblick uber die primitiv- und
-rekursiven Funktionen. Er ist gedacht als Hintergrundmaterial zur Erg anzung
der relativ knappen Abhandlung in der Vorlesung Einf uhrung in die Theoreti-
sche Informatik II.
1 Rekursive Funktionen
Rekursive Funktionen sind m oglicherweise der alteste konkrete Ansatz zur Erkl arung
von Berechenbarkeit (Dedekind 1888 [3]). Das Konzept entstand lange, bevor man uber
Maschinenmodelle nachdachte, und benutzt eine rein mathematische Vorgehensweise
um zu beschreiben, welche Funktionen berechenbar sind.
Das Konzept der rekursiven Funktionen geht dabei davon aus, da der Begriff der
Berechenbarkeit etwas intuitiv Einsichtiges sein ist. Bei einigen elementaren Funk-
tionen w urde niemand ernsthaft bezweifeln, da sie berechenbar sein m ussen. Hier-
zu z ahlt zum Beispiel die Nachfolgerfunktion (oft mit s bezeichnet), die bei Eingabe
einer nat urlichen Zahl x die n achstgr oere Zahl bestimmt, denn Z ahlen ist einer der
intuitivsten Berechnungsmechanismen. Auch die sogenannten Projektionsfunktionen,
die aus einer Gruppe von Werten x
1
, .., x
n
einen spezischen Wert x
k
herausgreifen
wir bezeichen sie mit pr
n
k
sind offensichtlich berechenbar und das gleiche gilt f ur
alle Konstantenfunktionen, also Funktionen, die unabh angig von der Eingabe x
1
, .., x
n
immer denselben Wert k zur uckgeben. Wir verwenden hierf ur die Bezeichnung c
n
k
.
Intuitiv einsichtig ist auch, da man berechenbare Funktionen auf verschiedene Ar-
ten zusammensetzen kann und dabei wieder eine berechenbare Funktion erhalten mu.
Dies gilt sicherlich f ur die einfache Komposition von Funktionen, also die Hintereinan-
derausf uhren mehrerer Berechnungen, bei der das Ergebnis einer Reihe von Funktio-
nen g
1
, .., g
n
als Eingabe f ur eine andere Funktion f dient, was man ublicherweise mit
f(g
1
, .., g
n
) bezeichnet.
Auch die Iteration einer Funktion f, also ihre wiederholte Anwendung auf ihr ei-
genes Ergebnis, ist ist offensichtlich leicht zu berechnen. Im Prinzip entspricht dies
einer vielfachen Komposition ff...f. Im Gegensatz dazu ist die Anzahl der Kom-
positionssschritte jedoch nicht fest vorgegeben, sondern abh angig von der Eingabe.
In der Mathematik verwendet man daher zur Beschreibung eine einfache Rekursion,
da dies pr aziser ist und (induktive) Beweise uber Eigenschaften berechenbarer Funk-
tionen vereinfacht.Die rekursive Betrachtung erlaubt es auch, die Iteration mehrstelli-
ger Funktionen zu beschreiben, was mit der einfachen Schreibweise ff...f nicht
m oglich ist. Bei der sogenannten primitiven Rekursion ubernimmt eine Initialfunktion
g die Berechnung des Startwertes f ur Null Iterationen, w ahrend eine Schrittfunktion h
die Rolle einer erweiterten Komposition ubernimmt: sie bestimmt, wie das bisherige
Funktionsergebnis, die Anzahl der bisher durchgef uhrten Iterationen und die restlichen
Eingabewerte im n achsten Iterationsschritt weiterverarbeitet werden. Wir verwenden
im folgenden die Bezeichnung Pr[g, h] f ur die so entstehende Funktion.
Primitive Rekursion und Komposition sind derart m achtige Mechanismen, da es
schwer ist, berechenbare Funktionen zu konstruieren, die nicht mit diesen Operationen
ausgedr uckt werden k onnen. Erst einige Jahrzehnte sp ater stellte sich heraus, da ei-
ne weitere Operation, die sogenannte Minimierung n otig war, um alle berechenbaren
Funktionen zu beschreiben. Minimierung, ublicherweise mit f bezeichnet, sucht die
erste Nullstelle der Funktion f. Im Prinzip ist auch dies wieder ein iterativer Prozess.
Im Gegensatz zur primitiven Rekursion wird allerdings die Anzahl der Iterationsschrit-
te zu Beginn nicht vorgegeben. Die Suche wird erst beendet, wenn sie erfolgreich war
und kann daher m oglicherweise nicht enden.
Es ist leicht einzusehen, da die oben beschriebenen Funktionen und Operationen
auf demPapier schematisch, also durch einfaches Befolgen einer Rechenvorschrift, aus-
gerechnet werden k onnen. Wichtig ist aber auch, wie diese Rechenvorschrift formali-
siert werden kann, so da keine Zweifel uber die durchzuf uhrende Berechnung ent-
stehen k onnen. Heutzutage w urde man daf ur eine Programmiersprache entwickeln, die
dann auf einem abstrakten Maschinenmodell, meist einer Art von Neumann Maschine,
ausgef uhrt wird. Diese Maschinenmodelle wurden aber erst 50 Jahre nach den rekursi-
ven Funktionen entwickelt und sind aus mathematischer Sicht auch wenig elegant,
da die Beschreibung der Bedeutung eines Programms aufwendig ist und Beweise meist
sehr kompliziert macht.
Der Kalk ul der rekursiven Funktionen wurde daher als Funktionenkalk ul gestaltet,
der zur Beschreibung von Berechenbarkeit nur die Funktionen selbst verwendet. Man
legt fest, welche Grundfunktionen als berechenbar gelten und welche Operationen auf
berechenbare Funktionen angewandt werden k onnen, um neue berechenbare Funktio-
nen zu erzeugen. Die Funktionsargumente tauchen in der Beschreibung der berechenba-
ren Funktionen uberhaupt nicht auf, sondern erst, wenn diese Funktionen f ur konkrete
Eingabewerte ausgerechnet werden sollen.
1
In diesem Sinne ist der Kalk ul der rekur-
siven Funktionen eine sehr abstrakte mathematische Programmiersprache, die man als
Vorl aufer des informatiktypischen Baukastensystems ansehen k onnte.
Die wesentliche Schwierigkeit f ur Informatiker liegt heutzutage in der Abstraktion,
also der Beschreibung des Funktionsverhaltens, ohne dabei explizit auf die Funktionsar-
gumente einzugehen. Wir wollen diese Vorgehensweise an einigen Beispielen erl autern.
Beispiel 1 (Abstrakte Funktionsbeschreibungen)
Wir wollen eine Beschreibung der Funktion +
2
nden, welche bei Eingabe einer
Zahl x den Wert x+2 berechnet, also 2 addiert. Dabei darf in der Beschreibung der
Funktion das Argument x nicht genannt werden.
Wir wissen, da x+2 dasselbe ist wie die zweifache Addition von 1, also x+1+1.
1
Diese Vorgehensweise ist aus der Analysis bekannt, in der der Ableitungsoperator d/dx eben-
falls nur auf Funktionssymbole ohne Argumente angewandt wird, um die erste Ableitung einer
Funktion als Funktion zu generieren.
2
Abstrahiert ist dies die doppelte Anwendung der Nachfolgerfunktions, also s(s(x)).
Damit ist die Funktion +
2
also die Komposition von s und s und die gesuchte Be-
schreibung ist +
2
ss.
Gesucht ist eine abstrakte Beschreibung der Addition zweier Zahlen x und y.
Das Ergebnis l at sich darstellen als y-fache Addition von 1: x+y = x+1+...+1
. .
ymal
.
Diese Iteration mu nun rekursiv beschrieben werden.
Der Initialwert f ur y = 0 ist eine null-fache Addition von 1 x+0 = x
Im Schrittfall verwenden wir das Ergebnis der Addition von x und y,
um die Addition von x und y+1 zu bestimmen x+(y+1) = (x+y)+1)
Wir m ussen nun diese Gleichungen als Funktionsanwendungen beschreiben. Der
Initialwert ergibt sich durch Anwendung der Projektion pr
1
1
auf die Eingabe x. Der
Schrittfall ergibt sich durch Anwendung von s auf das bisherige Funktionsergeb-
nis x+y. Die Anzahl y der bisher durchgef uhrten Iterationen und der Eingabewert
x werden nicht verwendet und m ussen durch eine entsprechende Projektion aus-
geblendet werden. Die Schrittfunktion h atte somit die Gestalt spr
3
i
, wobei i die
Position des bisherige Funktionsergebnisses unter den 3 Argumenten bezeichnet.
Bei der ublichen Formalisierung der primitiven Rekursion erwartet man das Funk-
tionsergebnis an der letzten Stelle aller Argumente. Damit w are die gesuchte Be-
schreibung der Additionsfunktion add = Pr[pr
1
1
, spr
3
3
]
Das kleinste gemeinsame Vielfache zweier Zahlen x und y l at sich am einfachsten
durch einen Suchproze beschreiben. Man sucht, beginnend bei der gr oeren der
beiden Zahlen x und y, die kleinste Zahl z, die von x und y geteilt wird.
Um diese Suche in der Denkweise der rekursiven Funktionen zu beschreiben, mu
man zun achst einen Test auf Teilbarkeit als rekursive Funktion t
divides
darstel-
len (siehe Beispiel 16), welche bei Eingabe (x, z) genau dann den Wert 0 liefert,
wenn x die Zahl y teilt. Addiert man dann die Ergebnisse von t
divides
(x, z) und
t
divides
(y, z), so bekommt man genau dann das Resultat 0, wenn beide Tests er-
folgreich waren.
Auf ahnliche Weise erg anzt man noch einen Test, ob xz bzw. yz gilt (siehe
Beispiel 9). Dies ergibt insgesamt eine rekursive Funktion f, die genau dann das
Resultat 0 liefert, wenn z ein gemeinsames Vielfaches von x und y und mindes-
tens so gro wie beide Zahlen ist, und die gesuchte Beschreibung des kleinsten
gemeinsamen Vielfachen ist kgV = f.
Eine detaillierte Herleitung der Beschreibung von kgV werden wir in Beispiel 15
auf Seite 15 angeben.
Wir werden im folgenden eine pr azise Denition der rekursiven Funktionen an-
geben und den Entwurf und die Analyse rekursiver Funktionen an einer Reihe von
Beispielen illustrieren. Dabei werden wir auch einige abgeleitete Programmiersche-
mata vorstellen, welche den Entwurf rekursiver Funktionen erheblich erleichtern. Wir
beginnen mit der wichtigen Unterklasse der primitiv-rekursiven Funktionen, stellen
anschlieend eine Funktion vor, die intuitiv berechenbar, aber nicht primitiv-rekursiv
ist, und betrachten schlielich die Erweiterung auf (-)rekursive Funktionen. Wir wer-
den beweisen, da die Klasse der rekursiven Funktionen identisch mit der der Turing-
berechenbaren Funktionen auf nat urlichen Zahlen ist. Somit k onnen Turingmaschinen
und rekursive Funktionen wahlweise dazu eingesetzt werden, um nachzuweisen, da
eine Funktion (bzw. ein teil davon) berechenbar ist.
3
2 Primitiv-rekursive Funktionen
Die Klasse der primitiv-rekursiven Funktionen ist die Menge aller Funktionen, die aus
elementaren Grundfunktionen durch beliebig h auge Anwendung von Komposition
und primitiver Rekursion aufgebaut werden k onnen. Wir werden sie im folgenden ofter
mit dem K urzel T! bezeichnen. Als Grundfunktionen verwenden wir die Nachfolger-
funktion, Projektionen und Konstanten.
Denition 2 (Grundfunktionen).
Die Nachfolgerfunktion s:NN ist deniert durch s(x) = x+1 f ur alle xN
Die Projektionsfunktionen pr
n
k
:N
n
N sind deniert durch pr
n
k
(x
1
, .., x
n
) = x
k
f ur alle x
1
, .., x
n
N, wobei nN und k 1..n.
Die Konstantenfunktionen c
n
k
:N
n
N sind deniert durch c
n
k
(x
1
, .., x
n
) = k f ur
alle x
1
, .., x
n
N wobei n, k N.
G =s pr
n
k
[ nN, 1kn c
n
k
[ n, k N ist die Menge der Grundfunktionen.
Es gibt minimalistische Formulierungen der rekursiven Funktionen, in denen als
Grundfunktionen nur die Nachfolgerfunktion, die Projektionen und die einstellige Null-
funktion z c
1
0
verwendet werden, da alle anderen Konstantenfunktionenhieraus durch
Komposition erzeugt werden k onnen. Andere Formulierungen verwenden anstelle von
pr
n
k
die Bezeichnungen id
n
k
oder
n
k
.
Denition 3 (primitiv-rekursive Operationen).
Die Komposition f(g
1
, .., g
n
):N
k
N der Funktionen f:N
n
N, g
1
, ..g
n
:N
k
N
f ur beliebige n, k N ist die eindeutig bestimmte Funktion h mit der Eigenschaft
h( x) = f( g
1
( x), .., g
n
( x) )
2
f ur alle xN
k
.
Die primitive Rekursion Pr[f, g]:N
k
N zweier Funktionen f:N
k1
N und
g:N
k+1
N f ur beliebige k1 ist die eindeutig bestimmte Funktion h f ur die gilt
h( x, 0) = f( x) und h( x, y+1) = g( x, y, h( x, y))
f ur alle xN
k1
und y N.
In der Denkweise imperativer Programmiersprachen
3
entspricht die Komposition
einer Folge von Anweisungen und die primitive Rekursion einer einfachen Z ahlschleife,
die allerdings in umgekehrter Reihenfolge abgearbeitet wird. Um h = f(g
1
, .., g
n
) zu
berechnen, w urde man folgende Anweisungen verwenden.
y
1
:= g
1
(x
1
,..,x
k
); ...; y
n
:= g
n
(x
1
,..,x
k
); h := f(y
1
,..,y
n
)
Um h = Pr[f, g] zu berechnen, w urde man folgende Schleife verwenden.
h := f(x
1
,..,x
k
); for i:=1 to y do h:= g(x
1
,..,x
k
,i-1,h)
Das Resultat h entspricht jeweils dem Funktionswert h(x
1
, .., x
k
).
2
x ist abk urzend f ur ein Tupel (x1, ..., xm) von nat urlichen Zahlen.
3
In funktionalen Programmiersprachen k onnen Komposition und primitive Rekursion wesent-
lich direkter ausgedr uckt werden. f(g1, .., gn) entspricht dem komplexen Ausdruck
fun (x
1
,..,x
k
) -> f( g
1
(x
1
,..,x
k
),..,g
n
(x
1
,..,x
k
) )
und Pr[f, g] einer einfachen rekursive Deklaration
let rec h( x,y) = if y=0 then f( x) else g( x,y-1,h( x,y-1) )
4
Denition 4 (primitiv-rekursive Funktionen).
Die Menge PRder primitiv-rekursiven Funktionen ist deniert als T! =
_

n=0
T!
n
.
Dabei sind die Klassen T!
i
induktiv wie folgt deniert.
T!
0
= ( und
T!
i+1
= T!
i
f(g
1
, .., g
n
) [ nN, f, g
1
...g
n
T!
i
Pr[f, g] [ f, g T!
i

In anderen Worten, T! besteht aus den Grundfunktionen und allen Funktionen,


die hieraus durch iterierte Komposition oder primitive Rekursion entstehen. T!
i
be-
schreibt die Funktionen, bei deren Aufbau maximal i Iterationen ben otigt. Die obige
Denition pr azisiert diesen intuitiven Gedanken, ist aber f ur nicht-Mathematiker oft
schwer zu handhaben. In vielen F allen ist die folgende Charakterisierung handlicher.
Korollar 5
1. Die Nachfolgerfunktion s ist primitiv-rekursiv.
2. Die Projektionsfunktionen pr
n
k
sind primitiv-rekursiv f ur alle nN und k 1..n.
3. Die Konstantenfunktionen c
n
k
sind primitiv-rekursiv f ur alle n, k N.
4. Die Komposition f(g
1
, .., g
n
):N
k
N der Funktionen f:N
n
N, g
1
, ..g
n
:N
k
N
ist primitiv-rekursiv f ur alle n, k N, wenn f, g
1
...g
n
primitiv-rekursiv sind.
5. Die primitive Rekursion Pr[f, g]:N
k
N zweier Funktionen f:N
k1
N und
g:N
k+1
Nist primitiv-rekursiv f ur alle k N, wenn f und g primitiv-rekursiv sind.
Will man also zeigen, da eine gegebene Funktion h primitiv-rekursiv ist, so mu
man wenn h nicht eine der Grundfunktionen ist entweder zeigen, da es primitiv-
rekursive Funktionen f, g
1
...g
n
gibt, so da h = f(g
1
, .., g
n
) ist, oder zwei primitiv-
rekursive Funktionen f und g nden, so da h = Pr[f, g] gilt. Zuweilen hilft es, f ur h
einen primitiv-rekursiven Ausdruck zu konstruieren, also einen Ausdruck, der nur aus
den Symbolen s pr
n
k
und c
n
k
und Anwendungen der Operatoren und Pr besteht. F ur
den Nachweis, da h primitiv-rekursiv ist, ist dies jedoch nicht erforderlich.
Wir wollen im folgenden die Analyse und Konstruktion primitiv-rekursiver Funk-
tionen an einigen Beispielen erkl aren und zeigen, da die wichtigsten arithmetischen
Funktionen primitiv-rekursiv sind.
2.1 Analyse und Konstruktion primitiv-rekursiver Funktionen
Es ist relativ leicht, einen vorgegebenen primitiv-rekursiven Ausdruck auf bestimm-
ten Argumenten auszurechnen. Man mu hierzu nur schrittweise die Interpretation
der Funktions- und Operationssymbole einsetzen, bis ein Ergebnis dasteht. Wegen der
groen Menge an Details sind Computer f ur diese T atigkeit normalerweise besser ge-
eignet als Menschen. Nichtsdestotrotz gewinnt man ein gewisses Verst andnis der Be-
griffe, wenn man dies an einfachen Beispielen von Hand durchrechnet.
Beispiel 6 (Auswertung eines primitiv-rekursiven Ausdrucks)
Wir wollen den Ausdruck Pr[pr
1
1
, spr
3
3
](5, 2) auswerten. Hierzu betrachten wir
zun achst den aueren Operator des Ausdrucks Pr[pr
1
1
, spr
3
3
]. Dieser ist Pr, d.h. der
Ausdruck hat die Gestalt h = Pr[f, g], wobei f = pr
1
1
NNund g = spr
3
3
N
3
N.
5
Die Denition der primitiven Rekursion Pr[f, g] (Denition 3) unterscheidet zwei
F alle: entweder ist das letzte Argument 0 oder es ist Nachfolger einer Zahl y. In unse-
rem Fall ist das letzte Argument eine 2, also der Nachfolger von 1, und wir beginnen
mit der Auswertung von h(x, y + 1) = g(x, y, h(x, y)) f ur x = 5 und y = 1, also von
g(5, 1, h(5, 1)) bzw. von spr
3
3
(5, 1, h(5, 1)).
An dieser Stelle gibt es zwei M oglichkeiten des weiteren Vorgehens. Wir k onnen
zun achst h(5, 1) weiter auswerten und anschlieend den aueren Ausdruck oder um-
gekehrt. In diesem Fall enth alt der auere Ausdruck eine Projektionsfunktion, deren
Auswertung einen Ausruck ublicherweise erheblich vereinfacht. Deswegen l osen wir
zun achst die Komposition spr
3
3
gem a Denition 3 auf und erhalten den Ausdruck
s(pr
3
3
(5, 1, h(5, 1))). Im n achsten Schritt wertet man nun die innere Projektionsfunkti-
on pr
3
3
aus, also pr
3
3
(5, 1, h(5, 1)) = h(5, 1), und erh alt s(h(5, 1)).
Nun m ussen wir erneut die primitive Rekursion h = Pr[f, g] erneut analysieren.
Jetzt ist das letzte Argument eine 1, also der Nachfolger von , und wir beginnen mit
der Auswertung von h(x, y + 1) = g(x, y, h(x, y)) f ur x = 5 und y = 0, also von
g(5, 0, h(5, 0)) bzw. von spr
3
3
(5, 0, h(5, 0)). Nach Au osen der Komposition und Aus-
wertung der innere Projektionsfunktion ergibt sich h(5, 1) = s(h(5, 0)), also insgesamt
h(5, 2) = s(h(5, 1)) = s(s(h(5, 0))).
In der nun folgenden Analyse der primitive Rekursion h = Pr[f, g] stoen wir auf
den Basisfall h(x, 0) = f(x) f ur x = 5, und berechnen h(5, 0) = f(5) = pr
1
1
(5) = 5.
Setzen wir dies in die obige Gleichung ein und werten weiter aus, so erhalten wir als
Endergebnis h(5, 2) = s(s(h(5, 0))) = s(s(5)) = s(6) = 7.
Die folgende Gleichungskette fat das obige Argument in knapper Form zusammen.
Pr[pr
1
1
, spr
3
3
](5, 2)
= spr
3
3
(5, 1, Pr[pr
1
1
, spr
3
3
](5, 1)) = s(pr
3
3
(5, 1, Pr[pr
1
1
, spr
3
3
](5, 1)))
= s(Pr[pr
1
1
, spr
3
3
](5, 1))
= s(spr
3
3
(5, 0, Pr[pr
1
1
, spr
3
3
](5, 0))) = s(s(pr
3
3
(5, 0, Pr[pr
1
1
, spr
3
3
](5, 0))))
= s(s(Pr[pr
1
1
, spr
3
3
](5, 0))) = s(s(pr
1
1
(5)))
= s(s(5)) = s(6) = 7
Diese Abarbeitungsreihenfolge ist nur eine von vielen M oglichkeiten. H atten wir vor-
rangig die inneren Ausdr ucke ausgewertet, so w are folgende Gleichungskette entstanden.
Pr[pr
1
1
, spr
3
3
](5, 2)
= spr
3
3
(5, 1, Pr[pr
1
1
, spr
3
3
](5, 1))
= spr
3
3
(5, 1, spr
3
3
(5, 0, Pr[pr
1
1
, spr
3
3
](5, 0))) = spr
3
3
(5, 1, spr
3
3
(5, 0, pr
1
1
(5)))
= spr
3
3
(5, 1, spr
3
3
(5, 0, 5)) = spr
3
3
(5, 1, s(pr
3
3
(5, 0, 5)))
= spr
3
3
(5, 1, s(5))
= spr
3
3
(5, 1, 6) = s(pr
3
3
(5, 1, 6))
= s(6) = 7
Anstelle einer geschlossenen Gleichungskette h atte man auch die Rekursion durch eine
Iteration ersetzen und die Werte Pr[pr
1
1
, spr
3
3
](5, i) f ur i = 0, 1, 2 der Reihe nach
berechnen k onnen. Dies ist f ur Menschen normalerweise ubersichtlicher, da sie kei-
nen Abarbeitungsstack verwalten m ussen. Einem Computer, der Ausdr ucke schematisch
verarbeiten mu, bleibt diese elegantere Vorgehnsweise nat urlich verwehrt.
6
Die Analyse eines vorgegebenen primitiv-rekursiven Ausdrucks beinhaltet neben
seiner Auswertung f ur konkrete vor allem nat urlich die Frage, welche mathematische
Funktion durch diesen Ausdruck berechnet wird und den Nachweis, da dies tats achlich
der Fall ist. Dabei liefert eine gr undliche Analyse oft alle wesentlichen Argumente f ur
den Beweis, so da dieser nur noch die Kernpunkte in einer schl ussigen Reihenfolge
zusammenfat.
Beispiel 7 (Analyse eines primitiv-rekursiven Ausdrucks)
Wir wollen den Ausdruck f
1
= Pr[pr
1
1
, spr
3
3
] aus Beispiel 6 genauer analysieren.
Hierzu betrachten wir zun achst einmal die Stelligkeit der Funktion f
1
. Nach Deni-
tion 3 ergibt sich die Stelligkeit von f
1
aus der Stelligkeit der Funktionen pr
1
1
und
spr
3
3
. In Denition 2 wurde die Projektionsfunktion pr
1
1
als einstellige Funktion auf
den nat urlichen Zahlen deniert, d.h. es gilt pr
1
1
:NN. pr
3
3
ist dreistellig und gem a
Denition 3 folgt auch spr
3
3
:N
3
N. Da die Stelligkeit von Pr[f, g] zwischen der von
f und g liegt, folgt damit, da f
1
zweistellig sein mu, also f
1
:N
2
N.
Um einen Eindruck vom Funktionsverhalten zu bekommen, werten wir als n achstes
f
1
auf einigen Beispielargumenten aus.
f
1
(2, 2) = Pr[pr
1
1
, spr
3
3
](2, 2)
= (spr
3
3
)(2, 1, f
1
(2, 1)) = s(pr
3
3
(2, 1, f
1
(2, 1)))
= s(f
1
(2, 1)) = s(Pr[pr
1
1
, spr
3
3
](2, 1))
= s((spr
3
3
)(2, 0, f
1
(2, 0))) = s(s(pr
3
3
(2, 0, f
1
(2, 0))))
= s(s(f
1
(2, 0))) = s(s(Pr[pr
1
1
, spr
3
3
](2, 0)))
= s(s(pr
1
1
(2)))
= s(s(2)) = s(3) = 4
f
1
(6, 1) = Pr[pr
1
1
, spr
3
3
](6, 1)
= (spr
3
3
)(6, 0, f
1
(6, 0)) = s(pr
3
3
(6, 0, f
1
(6, 0)))
= s(f
1
(6, 0)) = s(Pr[pr
1
1
, spr
3
3
](6, 0))
= s(pr
1
1
(6)) = s(6) = 7
f
1
(0, 0) = Pr[pr
1
1
, spr
3
3
](0, 0) = pr
1
1
(0) = 0
Das Ergebnis ist jeweils die Summe der beiden Eingaben, also liegt die Vermutung
nahe, da f
1
m oglicherweise die Additionsfunktion darstellt. Um dies zu uberpr ufen,
analysieren wir das rekursiven Verhalten von f
1
f ur beliebige Eingaben. F ur beliebige
x, y N ist
f
1
(x, 0) = pr
1
1
(x) = x
f
1
(x, y+1) = (spr
3
3
)(x, y, f
1
(x, y)) = s(f
1
(x, y)) = f
1
(x, y)+1
Bis auf die fehlende Inx-Notation ist dies genau die Rekursionsgleichung der Addition,
die wir aus den Peanoaxiomen kennen
x+0 = x
x+(y+1) = (x+y)+1
Damit ist bewiesen, da f
1
(x, y) = x+y f ur beliebige x, y N gilt und da f
1
die
Additionsfunktion add:N
2
N ist, die durch add(x, y) = x+y deniert ist. Auerdem
haben wir bewiesen, da die Additionsfunktion add primitiv-rekursiv ist.
7
Etwas schwieriger als die Analyse eines vorgegebenen primitiv-rekursiven Aus-
drucks ist der Nachweis, da eine bestimmte Funktion primitiv-rekursiv ist. Meist l auft
diese Aufgabe darauf hinaus, einer Beschreibung der Funktion in durch einen primitiv-
rekursiven Ausdruck zu nden, also im Endeffekt ein Programm in der Sprache T!
schreiben. Im Prinzip reicht es aber zu zeigen, da die Funktion sich durch Kompo-
sition und primitive Rekursion aus bekannten anderen primitiv-rekursiven Funktionen
zusammensetzen l at. Wenn man also bereits eine gewisse Bibliothek von primitiv-
rekursiven Funktionen zur Verf ugung hat, dann ist dieser Nachweis deutlich leichter
genauso, wie es in jeder anderen Programmiersprache leichter ist, Programme aus
bekannten Bibliotheksfunktionen zusammen zu setzen als sie von Grund auf neu zu
schreiben.
Erfahrungsgem a macht die primitive Rekursion den meisten dabei die gr oten
Schweirigkeiten. Man kennt die gesuchte Funktion h und mu nun zwei Funktionen f
und g nden mit der Eigenschaft, da h sich als Pr[f, g] darstellen l at. Dabei m ussen
vor allem die Rahmenbedingungen der Stelligkeiten und Anordnung der Argumente
eingehalten werden. f mu eine Stelle weniger haben als h und g eine mehr. g mu als
letztes Argument den Vorg angerwert der Rekursion verwenden, davor die Rekursions-
variable, also das letzte Argument von h, und davor die restlichen Argumente von h in
genau der gleichen Reihenfolge. Wie in jeder Programmiersprache darf von derartigen
formalen Rahmenbedingungen nicht abgewichen werden. Deswegen braucht man Pro-
jektionsfunktionen und Komposition, um die Argumente in der richtigen Anzahl und
an der richtigen Stelle einsetzen zu k onnen.
Um f und g zu nden, empehlt es sich, zun achst eine Funktionsgleichung f ur
die vorgegebene Funktion aufzustellen, in der nur bereits bekannte Funktionen und die
Argumente auftauchen. Dies kann eine Rekursionsgleichung sein, eine einfache Hinter-
einanderausf uhrung mehrerer Funktionen, oder eines der primitiv-rekursiven Program-
mierschemata enthalten, die wir im Abschnitt 2.2 diskutieren werden. Gelingt dies nicht
unmittelbar, so mu das Problem eventuell in kleinere Bestandteile zerlegt werden, f ur
die dann eine Funktionsgleichung aufgestellt wird. Die Gesamtl osung ergibt sich dann
durch Komposition der einzelnen Teill osungen.
F ur den Nachweis, da die vorgegebene Funktion h primitiv-rekursiv ist, reichen
diese Funktionsgleichungen aus. Man wei dann, da h sich durch Komposition und
primitive Rekursion aus anderen primitiv-rekursiven Funktionen ergibt und damit selbst
primitiv-rekursiv ist. Will man zus atzlich den primitiv-rekursiven Ausdruck angeben,
der h beschreibt, so mu man die Funktionsgleichungen in die Operatorschreibweise
umwandeln, indem man schrittweise die Argumente nach auen schiebt und hierf ur
ggf. Komposition und Projektionen einsetzt.
Beispiel 8 (Programmierung mit primitiver Rekursion)
Wir wollen zeigen, da die Vorg angerfunktion p:NN, deniert durch p(n) = n

1,
primitiv-rekursiv ist. Dabei beschreibt

die Subtraktion auf den nat urlichen Zahlen,
die im Gegensatz zur Subtraktion auf ganzen Zahlen keine negativen Werte annehmen
kann, d.h. x

y = 0, falls x<y. F ur xy ist x

y dasselbe wie xy.
Wir beginnen mit den Funktionsgleichungen f ur die Vorg angerfunktion. Wir wissen,
da p(n) = 0 f ur n<1 ist und p(n) = n1 f ur n1. Diese Fallunterscheidung ahnelt
dem Gleichungsschema der primitiven Rekursion in Denition 3, bis darauf, da die
8
Tatsache, da eine nat urliche Zahl gr oer als Null ist, dort durch die Schreibweise y+1
ausgedr uckt wird. Schreiben wir die Fallunterscheidung entsprechend um, so erhalten
wir folgende Funktionsgleichungen.
p(0) = 0

1 = 0
p(y+1) = (y+1)

1 = y
Wir m ussen nun noch die beiden F alle durch bekannte primitiv-rekursive Funktio-
nen ausdrucken, die den Vorschriften der primitiven Rekursion gen ugen. F ur den ersten
Fall m ussen wir also eine nullstellige Funktion f:N
0
N mit p(0) = f() nden und f ur
den zweiten Fall eine zweistellige Funktion g:N
2
N mit p(y+1) = g(y, p(y)).
Die einzige nullstellige Funktion, die den Wert p(0) = 0 als Ergebnis liefert ist die
nullstellige Konstantenfunktion c
0
0
. Wir w ahlen diese als unsere Funktion f. Die zwei-
stellige Funktion g mu nach obiger Bedingung bei Eingabe der Werte (y, p(y) das
Resultat p(y+1) = y liefern. Hierzu reicht es, das erste Argument y aus den zwei Ein-
gaben herausgreifen. Wir verwenden hierzu die zweistellige Projektionsfunktion pr
2
1
.
Insgesamt folgt also, da die Vorg angerfunktion p sich durch primitive Rekursi-
on aus den Funktionen f = c
0
0
und g = pr
2
1
ergibt und damit ist bewiesen, da die
Vorg angerfunktion p primitiv-rekursiv ist. Aus der obigen Analyse ergibt sich auch di-
rekt der primitiv-rekursive Ausdruck f ur die Vorg angerfunktion: p = Pr[c
0
0
, pr
2
1
].
Im folgenden geben wir eine Reihe von Beispielen primitiv-rekursiver Funktionen.
Wir beschr anken uns dabei auf die Angabe der Funktionsgleichungen und des entste-
henden primitiv-rekursive Ausdrucks und uberlassen es dem Leser, die n otigen Details
zu erg anzen.
Beispiel 9 (Wichtige primitiv-rekursive Funktionen)
Die Subtraktionsfunktion sub:N
2
N mit sub(n, m) = n

m ist primitiv-rekursiv.
Die zugeh origen primitiv-rekursiven Funktionsgleichungen lauten
sub(x, 0) = x = pr
1
1
(x)
sub(x, y+1) = x

(y+1) = (x

y)

1 = p(x

y) = (ppr
3
3
)(x, y, sub(x, y))
Damit entsteht sub durch primitive Rekursion aus primitiv-rekursiven Funktionen
und ist selbst primitiv-rekursiv. Der zugeh orige Ausdruck ist sub = Pr[pr
1
1
, ppr
3
3
]
Die Multiplikationsfunktion mul:N
2
Nmit mul(n, m) =nmist primitiv-rekursiv.
Die zugeh origen primitiv-rekursiven Funktionsgleichungen lauten
mul(x, 0) = 0 = c
1
0
(x)
mul(x, y+1) = x(y+1) = mul(x, y)+x = (add(pr
3
1
, pr
3
3
))(x, y, mul(x, y))
Damit ist mul primitiv-rekursiv. Der zugeh orige primitiv-rekursive Ausdruck ist
mul = Pr[c
1
0
, (add(pr
3
1
, pr
3
3
))]
Die Exponentialfunktion exp:N
2
N mit exp(n, m) = n
m
ist primitiv-rekursiv.
Die zugeh origen primitiv-rekursiven Funktionsgleichungen lauten
exp(x, 0) = 1 = c
1
1
(x)
exp(x, y+1) = x
y+1
= exp(x, y)x = (mul(pr
3
1
, pr
3
3
))(x, y, exp(x, y))
Damit ist mul primitiv-rekursiv. Der zugeh orige primitiv-rekursive Ausdruck ist
exp = Pr[c
1
1
, (mul(pr
3
1
, pr
3
3
))]
9
Die Fakult atsfunktion fak:NNmit fak(n) =n! =1*2*...*nist primitiv-rekursiv.
Die zugeh origen primitiv-rekursiven Funktionsgleichungen lauten
fak(0) = 1 = c
0
1
()
fak(y+1) = (y+1)! = (y+1)fak(y) = (mul(spr
2
1
, pr
2
2
))(y, fak(y))
Damit ist fak primitiv-rekursiv. Der zugeh orige primitiv-rekursive Ausdruck ist
fak = Pr[c
0
1
, (mul(spr
2
1
, pr
2
2
))]
Die Vorzeichenfunktion sign:NN mit sign(n) =
_
0 falls n=0
1 sonst
ist primitiv-rekursiv.
F ur diese Funktion gibt es eine Reihe verschiedenartiger Bezeichnungen, wie zum
Beispiel Signum-Funktion und Test auf 0 (t
0
).
4
Die zugeh origen primitiv-rekursiven
Funktionsgleichungen lauten
sign(0) = 0 = c
0
0
()
sign(y+1) = 1 = c
2
1
(y, sign(y))
Damit ist sign primitiv-rekursiv. Der zugeh orige Ausdruck ist sign = Pr[c
0
0
, c
2
1
]
Der Gr oenvergleichstest t

:N
2
N mit t

(n, m) =
_
0 falls nm
1 sonst
ist primitiv-rekursiv.
F ur diese Funktion brauchen wir keine Rekursionsgleichung, denn xy gilt genau
dann, wenn xy0 bzw. wenn x

y = 0 ist. Damit ergibt sich t

durch Kom-
position aus Subtraktion und Vorzeichenfunktion und ist primitiv rekursiv. Der zu-
geh orige Ausdruck ist t

= signsub
Der Gleichheitstest t
=
:N
2
N mit t
=
(n, m) =
_
0 falls n=m
1 sonst
ist primitiv-rekursiv.
Den Beweis dieser Aussage und die Konstruktion des entsprechenden primitiv-
rekursiven Ausdrucks uberlassen wir dem Leser als

Ubungsaufgabe.
Wir werden sp ater weitere wichtige Funktionen als primitiv-rekursiv nachweisen. Zu-
vor stellen wir jedoch einige Programmierschemata vor, die primitiv-rekursive Funk-
tionen auf einfache Weise zu neuen primitiv-rekursiven Funktionen zusammensetzen
k onnen und die Menge der verwendbaren primitiv-rekursiven Operatoren erweiteren.
4
In der Theorie der rekursiven Funktionen hat es sich eingeb urgert, bei Testfunktionen im Er-
folgsfall eine 0 zur uckzugeben und sonst einen Wert, der gr oer als 0 ist. Dies liegt zum Teil
daran, da die Null das Grundelement der nat urlichen Zahlen bildet und damit eine herausra-
gende Rolle gegen uber allen anderen Zahlen besitzt. Auerdem ist es in vielen Anwendungen
einfacher, nach Nullen zu suchen, als nach Einsen. Im Gegensatz dazu identiziert man in der
booleschen Algebra den Wert wahr meist mit der 1 und die 0 mit dem Wert falsch.
Dadurch ergibt sich eine unvermeidbare Diskrepanz zwischen den von der booleschen Alge-
bra gepr agten charakteristischen Funktionen, die wir im Kontext der Turing-Berechenbarkeit
eingef uhrt hatten, und zahlentheoretisch gepr agten Testfunktionen im Kontext der rekursiven
Funktionen, die wir in diesem Artikel verwenden. Aus theoretischer Sicht ist dieser Unter-
schied unbedeutend, aber beim konkreten Ausprogrammieren einer Funktion mu nat urlich
darauf geachtet werden, die passenden Ausgabewerte zu generieren.
10
2.2 Primitiv-rekursive Programmierschemata
Eines der h augsten Schemata in der Programmierung ist die Fallunterscheidung, auch
Konditional genannt. Man f uhrt einen Test durch und w ahlt abh angig vom Ergebnis
eine von zwei m oglichen Funktionen aus. Wir werden zeigen, da dieses Schema immer
eine primitiv-rekursive Funktion liefert, wenn der Test und die beteiligten Funktionen
primitiv-rekursiv sind.
Denition 10 (Fallunterscheidung).
Das Konditional Cond[t, f, g]:N
k
N der Funktionen t,f,g:N
k
N f ur beliebige k N
ist die eindeutig bestimmte Funktion h mit der Eigenschaft h( x) =
_
f( x) falls t( x)=0
g( x) sonst
Theorem 1. Das Konditional Cond[t, f, g]:N
k
N der Funktionen t,f,g:N
k
N ist
primitiv-rekursiv f ur alle k N, wenn t, f und g primitiv rekursiv sind.
Beweis: Sei h = Cond[t, f, g]. h nimmt den Wert von f an, wenn die Testfunktion
den Wert 0 annimmt und den Wert von g, wenn die Testfunktion einen Wert gr oer
als 0 annimmt. Wir verwenden einen einfachen numerischen Trick, um dies von
Additionen und Multiplikationen zu denieren.
Wir wissen, da f( x) = 1f( x) = 1f( x)+0g( x) und g( x) = 0f( x)+1g( x)
gilt. Um also die Fallunterscheidung zu berechnen, m ussen wir f mit 1 multiplizie-
ren und g mit 0, wenn die Testfunktion den Wert 0 annimmt und f mit 0 multipli-
zieren und g mit 1, wenn die Testfunktion einen Wert gr oer als 0 annimmt. Das
bedeutet, der Faktor f ur f mu den Wert der Testfunktion umdrehen, was man
erreichen kann, wenn man ihn von 1 abzieht, und der Faktor f ur g mu den Wert der
Testfunktion normieren, was man mit der Vorzeichenfunktion erreichen kann.
Damit erhalten wir h( x) = (1

t( x)) f( x) +sign(t( x)) g( x), d.h. h ergibt sich
durch Komposition aus Addition, Multiplikation, Subtraktion und Vorzeichenfunk-
tion und ist primitiv rekursiv. Der zugeh orige Ausdruck ist f ur beliebige t, f und g
Cond[t, f, g] = add(mul(sub(c
k
1
, signt), f), mul(signt, g))

Viele mathematische Funktionen lassen sich nat urlich durch Aufsummieren oder
Aufmultiplizieren uber eine andere Funktion beschreiben. So ist zum Beispiel die Fa-
kult at n! das Produkt

n
i=1
i der Zahlen zwischen 1 und n und die Potenz x
n
das
n-fache Produkt

n
i=1
x der Zahl x. Wir zeigen nun, da die Summe und das Produkt
uber eine Funktion f primitiv-rekursiv ist, wenn dies f ur die beteiligte Funktion f gilt.
Denition 11 (Generelle Summe und generelles Produkt).
Die Generelle Summe f:N
k
N der Funktion f:N
k
N f ur beliebige k1 ist die
eindeutig bestimmte Funktion h mit der Eigenschaft h( x, y) =
y
i=0
f( x, i) f ur
alle x N
k1
und y N.
Das Generelle Produkt f:N
k
N der Funktion f:N
k
N f ur beliebige k1 ist
die eindeutig bestimmte Funktion h mit der Eigenschaft h( x, y) =
y
i=0
f( x, i) f ur
alle x N
k1
und y N.
11
Theorem 2. Die Generelle Summe f:N
k
Nund das Generelle Produkt f:N
k
N
sind primitiv-rekursiv f ur alle k1, wenn f primitiv rekursiv ist.
Beweis: Sei h = f. Dann gilt
h( x, 0) =

0
i=0
f( x, i) = f( x, 0)
h( x, y+1) =

y+1
i=0
f( x, i) =

y
i=0
f( x, i))+f( x, y+1) = h( x, y)+f( x, y+1)
Damit entsteht h durch primitive Rekursion aus primitiv-rekursiven Funktionen
und ist selbst primitiv-rekursiv. Der zugeh orige Ausdruck lautet f ur k=2
f = Pr[f(pr
1
1
, c
1
0
), add(pr
3
3
, f(pr
3
1
, spr
3
2
))].
F ur andere k mu der Ausdruck entsprechend an die ver anderte Anzahl der restli-
chen Argumente angepat werden. F ur k=1 lautet der Ausdruck zum Beispiel
f = Pr[fc
0
0
, add(pr
2
2
, f(spr
2
1
))].
Der Beweis daf ur, da f primitiv-rekursiv ist, verl auft analog. Die Gleichungen
lauten nun

0
i=0
f( x, i) = f( x, 0) und

y+1
i=0
f( x, i) =

y
i=0
f( x, i))f( x, y+1)
und der primitiv-rekursive Ausdruck f ur f und k=2 ist
f = Pr[f(pr
1
1
, c
1
0
), mul(pr
3
3
, f(pr
3
1
, spr
3
2
))]
Eine h aug verwendete einfache Form der primitiven Rekursion ist die Iteration, also
deren vielfache Anwendung f(f(...f(x)))
. .
kmal
einer Funktion. Sie wird ublicherweise
mit f
k
(x) bezeichnet wird.
Denition 12 (Iteration einer Funktion).
Die Iteration f:N
2
N der Funktion f:NN ist die eindeutig bestimmte Funktion h
mit der Eigenschaft h(x, k) = f
k
(x).
Theorem 3. Die Iteration f:N
2
Neiner Funktion f:NNist primitiv rekursiv, wenn
f primitiv rekursiv ist.
Beweis: Sei h = f. Dann gilt
h(x, 0) = x = pr
1
1
(x)
h(x, y+1) = f
y+1
(x) = f(h(x, y)) = fpr
3
3
(x, y, (h(x, y)
h entsteht also durch primitive Rekursion aus primitiv-rekursiven Funktionen und
ist daher primitiv-rekursiv. Der zugeh orige Ausdruck ist f

= Pr[pr
1
1
, fpr
3
3
].
Viele berechenbare Funktionen lassen sich erheblich leichter durch einen Suchproze
beschreiben als durch eine primitive Rekursion. So ist das kleinste gemeinsame Viel-
fache zweier Zahlen x und y, wie in Beispiel 1 illustriert, unmittelbar durch eine Su-
che nach der kleinsten Zahl z, die Vielfaches von x und y ist, charakterisiert, w ahrend
eine rekursive Beschreibung des kgV schwierig ist. Suchprozesse werden ublicherwei-
se durch einen Startwert und eine Abbruchbedingung charakterisiert, wobei die Ab-
bruchbedingung ublicherweise durch das Ergebnis 0 einer Testfunktion dargestellt wird.
Damit wird also die kleinste Nullstelle einer berechenbaren Funktion f gesucht, ein
Proze, den man oft auch als Minimierung bezeichnet. Wir werden nun zeigen, da
die Suche nach der kleinsten Nullstelle einer primitiv-rekursiven Funktion wieder eine
primitiv-rekursive Funktion ist, sofern eine Obergrenze f ur die Suche angegeben wird.
In diesem Fall spricht man von einer beschr ankten Minimierung.
12
Denition 13 (Beschr ankte Minimierung und Maximierung).
Die beschr ankte Minimierung Mn[f]:N
k
N der Funktion f:N
k
N f ur beliebige
k1 ist die eindeutig bestimmte Funktion h mit der Eigenschaft
h( x, y) =
_
minzy [ f( x, z)=0 falls dies existiert
y+1 sonst
Die beschr ankte Maximierung Max[f]:N
k
N der Funktion f:N
k
N f ur belie-
bige k1 ist die eindeutig bestimmte Funktion h mit der Eigenschaft
h( x, y) =
_
maxzy [ f( x, z)=0 falls dies existiert
y+1 sonst
Theorem 4. Die beschr ankte Minimierung Mn[f]:N
k
N und die beschr ankte Maxi-
mierung Max[f]:N
k
N sind primitiv-rekursiv f ur alle k1, wenn dies f ur f gilt.
Beweis: Sei h = Mn[f]. Dann gilt
h( x, 0) =
_
0 falls f( x, 0) = 0
1 sonst
h( x, y+1) =
_
_
_
h( x, y) falls h( x, y)y
y+1 falls h( x, y) = y+1 und f( x, y+1) = 0
y+2 sonst
Damit entsteht h durch primitive Rekursion aus primitiv-rekursiven Funktionen
und ist selbst primitiv-rekursiv.
Der zugeh orige Ausdruck ist relativ komplex und wegen der notwendigen Projek-
tionen abh angig von der Anzahl der Argumente. Normalerweise w urde man ihn
nicht explizit konstruieren. Der Vollst andigkeit halber werden wir ihn beispielhaft
f ur k=2 herleiten. Wegen der obigen Funktionsgleichungen wissen wir, da der
Ausdruck f ur Mn[f] die Gestalt Pr[f

, g] hat, wobei
f

( x) = sign(f( x, 0))
g( x, y, z) =
_
_
_
z falls zy
y+1 falls z = y+1 und f( x, y+1) = 0
y+2 sonst
Der Teilausdruck f ur f

ist leicht zu konstruieren: f

= signf(pr
1
1
, c
1
0
).
Der Teilausdruck f ur g hat die Form g = Cond[t
1
, f
1
, Cond[t
2
, f
2
, g
2
], besteht al-
so aus einem verschachtelten Konditional. Dabei vergleicht der erste Test das dritte
und das zweite Argument und im Erfolgsfall ist das Ergebnis das dritte Argument,
d.h. t
1
= t

(pr
3
3
, pr
3
2
) und f
1
= pr
3
3
. Der zweite Test vergleicht das dritte
Argument und den Nachfolger des zweiten und testet ob f( x, y+1) den Wert 0
ergibt. Addiert man die beiden testtteile, so erh alt man eine 0 genau dann, wenn
beide tests erfolgreich sind. Damit ergibt sich als Teilausdruck ur den zweiten Test
t
2
= add( t
=
(pr
3
3
, spr
3
2
), f(pr
1
1
, spr
3
2
) ) und f ur die beiden Ergebnisfunk-
tionen f
2
= spr
3
2
sowie g
2
= sspr
3
2
. Setzt man all diese Teilausdr ucke
zusammen, so ergibt sich folgender Ausdruck
Mn[f] = Pr[signf(pr
1
1
, c
1
0
),
Cond[t

(pr
1
1
, pr
1
1
), pr
3
3
,
Cond[add( t
=
(pr
3
3
, spr
3
2
), f(pr
1
1
, spr
3
2
) ),
spr
3
2
, sspr
3
2
] ]]
13
Der Beweis daf ur, da Max[f] primitiv-rekursiv ist, k onnte analog gef uhrt werden.
Es ist aber einfacher, sich die beschr ankte Minimierung zunutze zu machen und die
Suchreihenfolge umzudrehen. Sucht man nach dem gr oten zy mit f( x, z)=0,
so kann man auch nach dem kleinsten z

y suchen, f ur das die Funktion f

mit
f

( x, z

) = f( x, yz

) den Wert 0 annimt. Im Erfolgsfall ist dann z = yz

.
Damit ist Max[f]( x, y) =
_
y

Mn[f

]( x, y) falls yMn[f

]( x, y)
y+1 sonst
Daraus folgt, da Max[f] primitiv-rekursiv ist. Die explizite Konstruktion des zu-
geh origen Ausdrucks sei dem Leser uberlassen.
Die beschr ankte Minimierung und Maximierung wird selten in ihrer Grundversion ver-
wendet, da hierbei eine Funktion entsteht, welche die obere Grenze als expliziten Pa-
rameter ben otigt. In den allermeisten F allen wird die obere Grenze aus den anderen
Argumenten berechnet oder als Konstante vorgegeben. Wir verwendent die Notationen
Mn
g
[f] bzw. Mn
y
[f] f ur diese beiden Spezialf alle, wobei g eine primitiv-rekursive
Funktion und y eine nat urliche Zahl ist. Damit ist
Mn
g
[f]( x) =
_
minzg( x) [ f( x, z)=0 falls dies existiert
g( x)+1 sonst
und
Mn
y
[f]( x) =
_
minzy [ f( x, y)=0 falls dies existiert
y+1 sonst
Zu beachten ist dabei, da die Stelligkeit von Mn
g
[f] und Mn
y
[f] um 1 geringer ist
als die von f bzw. Mn[f], da die Obergrenze der Suche durch den Parameter g bzw. y
bestimmt wird. Beide Operationen k onnen leicht mithilfe der allgemeinen beschr ankten
Minimierung beschrieben werden, denn es ist Mn
g
[f]( x) = Mn[f]( x, g( x)) und
Mn
y
[f]( x) = Mn[f]( x, y). Damit ist Mn
g
[f] primitiv rekursiv, wenn f und ggf. g
primitiv rekursiv sind. Mn
y
[f] ist primitiv rekursiv f ur alle y N, wenn f primitiv
rekursiv ist. Die zugeh origen primitiv-rekursiven Ausdr ucke sind (f ur k=2)
Mn
g
[f] = Mn[f](pr
1
1
, g) und Mn
y
[f] = Mn[f](pr
1
1
, c
1
y
)
Theorem 4 zeigt, da begrenzte Suchschleifen nicht m achtiger sind als einfache Z ahl-
schleifen, da jede beschr ankte Minimierung durch einen primitiv-rekursiven Ausdruck
ersetzt werden kann. Nichtsdestotrotz ist das Programmieren mit Suchschleifen oft
erheblich eleganter, wie die folgenden Beispiele zeigen.
Beispiel 14 (Integer-Quadratwurzel)
Die Integer-Quadratwurzelfunktion sqrt:NNist deniert durch sqrt(x) =

x.
Sie bestimmt den ganzzahligen Anteil der Quadratwurzel von n, also die eindeutig be-
stimmte Zahl z N mit der Eigenschaft z
2
x < (z+1)
2
.
Ein L osungsansatz mit primitiver Rekursion ben otigt die Funktionsgleichungen
sqrt(0) = 0
sqrt(x+1) =
_
sqrt(x)+1 falls (sqrt(x)+1)
2
x+1
sqrt(x) sonst
die nun in einen primitiv-rekursiven Ausdruck ubersetzt werden m ussen. Es ergibt sich
sqrt = Pr[c
0
0
, Cond[t

(sqrspr
2
2
, spr
2
1
), spr
2
1
, pr
2
1
] ],
wobei sqr = mul(pr
1
1
, pr
1
1
) die Quadratfunktion ist.
14
Ein L osungsansatz mit begrenzer Suche ben otigt nur die Erkenntnis, da sqrt(x) das
gr ote z mit z
2
x ist, wobei als Obergrenze f ur die Suche die Zahl x selbst dienen
kann. Damit ist die f:N
2
N mit f(x, z) = t

(z
2
, x) die Funktion, deren maximale
Nullstelle gesucht werden mu: sqrt = Max
pr
1
1
[t

(sqrpr
2
2
, pr
2
1
)]
Dieser Ausdruck ist nicht nur einfacher, sondern auch schneller zu verarbeiten. F ur
eine efziente Verarbeitung d urfen wir allerdings nicht den primitiv-rekursiven Aus-
druck f ur die Minimierung einsetzen, sondern ben otigen den echten Minimierungs-
operator, den wir sp ater in Denition 24 auf Seite 23 vorstellen werden.
Beispiel 15 (Kleinstes gemeinsames Vielfaches)
Die Funktion kgV :N
2
N bestimmt bei Eingabe zweier Zahlen x und y ist die
kleinste Zahl z mit der Eigenschaft, da z von x und y geteilt wird.
Ein L osungsansatz mit begrenzter Suche besteht aus nichts anderem als einer For-
malisierung dieser Denition. Gesucht wird die kleinste Zahl z, welche folgende vier
Bedingungen erf ullt: xteilt z und yteilt z und xz und yz. Dabei sollen die letzten
beiden Bediingungen verhindern, da die Zahl 0 als kleinstes gemeinsames Vielfaches
akzeptiert wird, wenn eine der beiden Zahlen gr oer als 0 ist, denn 0 wird von jeder
Zahl geteilt. Als Obergrenze f ur die Suche kann xy gew ahlt werden. Da Teilbarkeit
und Gr oenvergleich nach Beispiel 16 bzw. 9 primitiv rekursiv sind, ist damit gezeigt,
da kgV ebenfalls primitiv rekursiv ist.
F ur die Konstruktion des primitiv-rekursiven Ausdrucks verwendet man die Tests
t
divides
und t

aus Beispiel 16 bzw. 9. f:N


3
N mit f(x, y, z) = t
divides
(x, z) +
t
divides
(y, z) +t

(x, z) +t

(y, z) ist die Funktion, deren minimale Nullstelle gesucht


werden mu. Der Ausdruck ist damit strukturell sehr einfach und wird nur durch die
erforderlichen Projektionen etwas komplexer.
kgV = Mn
mul
[add(add(t
divides
(pr
3
1
, pr
3
3
), t
divides
(pr
2
1
, pr
3
3
)),
add(t

(pr
3
1
, pr
3
3
), t

(pr
2
1
, pr
3
3
)))]
Ein L osungsansatz mit primitiver Rekursion w urde erkl aren m ussen, wie kgV (x, y+1))
nur aus x, y und kgV (x, y)) berechnet werden kann. Zwischen kgV (x, y+1)) und
kgV (x, y)) besteht jedoch kein unmittelbarer Zusammenhang, so da dieser Ansatz
nur auf Umwegen zum Erfolg f uhrten kann.
Begrenzte Suche, primitive Rekursion und Komposition erm oglichen es, nahezu je-
den Mechanismus zu simulieren, der in der Beschreibung arithmetischer Funktionen
vorkommt. Die folgende Beispiele stellen einige wichtige primitiv-rekursive Funktio-
nen vor, die zum Teil mit einfachen Kompositionen und zum Teil nur mit Minimierung
programmiert werden k onnen. Die Beweise und die Konstruktion der entsprechenden
primitiv-rekursiven Ausdr ucke uberlassen wir dem Leser als

Ubungsaufgabe.
Beispiel 16 (Weitere wichtige primitiv-rekursive Funktionen)
Die folgenden Funktionen sind primitiv rekursiv.
Die absolute Differenz absdi :N
2
N mit absdi (n, m) = [nm[
Das Maximum max:N
2
N mit max(n, m) =
_
n falls nm
m sonst
Das Minimum min:N
2
N mit min(n, m) =
_
n falls nm
m sonst
15
Die Division div:N
2
N mit div(n, m) = nm
Der Divisionsrest mod:N
2
N mit mod(n, m) = n mod m
Der Teilbarkeitstest t
divides
:N
2
N mit t
divides
(n, m) =
_
0 falls nteilt m
1 sonst
Der Primzahltest t
prim
:NN mit t
prim
(n) =
_
0 falls nPrimzahl
1 sonst
Der duale Integer-Logarithmus: ld:NN mit ld(n) = log
2
n
Der gr ote gemeinsamer Teiler ggT:N
2
N mit
ggT(n, m) = maxz [ z teilt xz teilt y
2.3 Berechnungen auf Zahlenpaaren und -listen
In einigen der bisherigen Beispiele und Konstruktionen stellte sich heraus, da eine un-
bestimmte Anzahl von Argumenten bei der Konstruktion primitiv-rekursiver Ausdr ucke
ein Hindernis darstellte und man f ur jede m ogliche Anzahl einen separaten Ausdruck
konstruieren mute. Der wesentliche Unterschied zwischen den einzelnen Ausdr ucken
war dabei die Stelligkeit und Anzahl der Projektionsfunktionen, die verwendet werden
muten umzumBeispiel auf das letzte und vorletzte Argument zuzugreifen. Die Grund-
struktur des Ausdrucks war dagegen immer die gleiche. In sp ateren Beweisen werden
wir zudem noch rekursive Funktionen ben otigen, die auf Listen von Zahlen, also einer
wechselnden Anzahl von Argumenten arbeiten.
Beide Probleme sind leicht zu l osen, wenn man es schafft, mehrere Argumente
durch ein einziges zu codieren, also Tupel und Listen nat urlicher Zahlen bijektive und
berechenbar durch eine einzige nat urliche Zahl zu repr asentieren. Dies w urde zudem
auch noch erm oglichen, Funktionen mit mehreren Ein- und mehreren Ausgaben auf
einheitliche Art zu beschreiben und hierf ur einstellige Funktionen zu verwenden.
Wenn man, wie heute ublich, alle Daten eines Programms bin ar codiert, dann ist es
nicht verwunderlich, da man mehrere Zahlen durch eine einzige Zahl darstellen kann.
Man mu hierzu nur die einzelnen Bitketten aneinanderh angen und das Ergebnis als
Zahl interpretieren. Hierbei mu man allerdings einige Details ber ucksichtigen.
Interessanter und mathematisch eleganter als ein Umweg uber Bitketten ist aber, die
Codierung von Zahlentupeln und -listen auf rein arithmetischer Basis durchzuf uhren.
Die wohl bekannteste Form ist G odel-Codierung von Zahlenfolgen durch Primzahlpo-
tenzen [?], bei der die i-te Zahl einer Liste als Potenz der i-ten Primzahl verwendet
und alle Primzahlpotenzen aufmultipliziert werden. Diese Codierung, mit der z.B. das
Tupel (4, 2, 1, 1) durch die Zahl 2
4
3
2
5 7 = 5040 repr asentiert wird, ist zwar
mathematisch sehr elegant, aber vom Berechnungsaufwand relativ komplex.
Daneben gibt es aber auch eine sehr einfache Codierung von Zahlenpaaren, die
leicht auf groere Tupel und listen fortgesetzt werden kann. Die Idee ist dabei, Paaren
von Zahlen (x, y) einen Wert zuzuweisen, indem man schrittweise die Wertetabelle der
Funktion mit Zahlen auff ullt. Man beginnt am Nullpunkt mit dem Ergebnis 0 und f ullt
dann, wie in Tabelle 2.3 illustriert jeweils diagonale Linien mit konstantem x+y-Wert
der Reihe nach mit immer gr oer werdenden Zahlen auf. Die so entstehende Funkti-
on weist jedem Zahlenpaare eine eindeutige Nummer zu und wird im folgenden als
Standard-Tupelfunktion bezeichnet.
16
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. ...
5 20 ...
4 14 19 ...
3 9 13 18 ...
2 5 8 12 17 ...
1 2 4 7 11 16 ...
0 0 1 3 6 10 15 ...
y/x 0 1 2 3 4 5 ...
Tabelle 1. Ergebnistabelle der Standard-Tupelfunktion
Da jede Diagonale mit dem konstantemx+y-Wert genau x+y+1 Elemente enth alt,
l at sich die Standard-Tupelfunktion auch gut numerisch beschreiben. An der Stelle
x=0 hat sie den Wert (

x+y
i=1
i) und f ur gr oere y erh oht sich dieser Wert genau um y.
Diese Beobachtung f uhrt zu folgender Denition.
Denition 17 (Standard-Tupelfunktion).
Die Standard-Tupelfunktion :N
2
N ist deniert durch
x, y = (
x+y

i=1
i) + y = (x+y)(x+y+1)2 + y
Gelegentlich wird die Standard-Tupelfunktion auch mit bezeichnet, was sich wesent-
lich leichter aussprechen l at als . Sie hat eine Reihe wichtiger Eigenschaften.
Theorem 5.
1. :N
2
N ist primitiv-rekursiv
2. :N
2
N ist bijektiv
3. Die Umkehrfunktionen
i
:NNvon , deniert durch
i
= pr
2
i

1
f ur i 1, 2
sind primitiv-rekursiv
Beweis:
1. kann durch eine Komposition von Addition, Multiplikation und Division
beschrieben werden und ist damit primitiv rekursiv. Der zugeh orige primitiv-
rekursive Ausdruck ergibt sich unmittelbar aus der obigen Gleichung.
2. Wir m ussen zeigen, da injektiv und surjektiv ist.
Um zu zeigen, da injektiv ist, nehmen wir an, da (x, y),=(x

, y

) ist und
zeigen x, y, =x

, y

.
Liegen (x, y) und (x

, y

) auf derselben Diagonale, dann gilt x+y = x

+y

,
aber x,=x

und y,=y

. In diesem Fall ist


x, y = (x+y)(x+y+1)2 + y = (x

+y

)(x

+y

+1)2 + y
,=(x

+y

)(x

+y

+1)2 + y

= x

, y

.
Liegen (x, y) und (x

, y

) nicht auf derselben Diagonale, dann ist o.B.d.A.


x+y < x

+y

, also x+y+1x

+y

. Es folgt
x

, y

= (x

+y

)(x

+y

+1)2 + y

(x+y+1)(x+y+2)2 + y

= (x+y+1)(x+y)2 + x+y+1 + y

>(x+y+1)(x+y)2 + y = x, y
17
Um zu zeigen, da surjektiv ist, zeigen wir per Induktion, da f ur alle nN
ein Paar (x, y) existiert mit x, y = n.
F ur n = 0 w ahlen wir x = y = 0, denn es gilt 0, 0 = 0.
Sei x, y = n. Wir konstruieren (x

, y

) mit x

, y

= n+1.
Falls x = 0 ist, dann ist
n+1 = x, y+1 = y(y+1)2 +y+1 = (y+2)(y+1)2 +0 = y+1, 0
Sonst ist n+1 = x, y+1 = (x+y)(x+y+1)2 + y+1 = x1, y+1
Damit existiert in jedem Fall ein (x

, y

) mit x

, y

= n+1.
3. Zur Konstruktion der Umkehrfunktionen bestimmen wir zun achst den x+y-
Wert der Diagonalen, auf der sich der Eingabewert n bendet. Aus der Glei-
chung f ur x, y lassen sich dann zun achst y und daraus x leicht bestimmen.
Es sei g(n) = minz [ (z+1)(z+2)2 > n. Dann ist g:NN durch eine
Minimierung mit Obergrenze n konstruierbar und somit primitiv rekursiv. Per
Konstruktion ist g(n), 0n und g(n)+1, 0>n. Damit beschreibt g(n) den
x+y-Wert der Diagonalen von n und f ur das Paar (x, y) mit x, y = n folgt

2
(n) = y = n g(n)(g(n)+1)2 und
1
(n) = x = g(n) y.
Damit ist gezeigt, da beide Umkehrfunktionen primitiv rekursiv sind.
Der Vollst andigkeit halber geben wir zus atzlich die zugeh origen Ausdr ucke an
g = Mn
pr
1
1
[t

(spr
2
1
, div(mul(spr
2
2
, sspr
2
2
), c
1
2
))]

2
= sub(pr
1
1
, div(mul(g, sg), c
1
2
)

1
= sub(g,
2
).

Die Standard-Tupelfunktion kann iterativ auf Tupel aus N


k
f ur beliebige k und
auf endliche Listen von Zahlen aus N

fortgesetzt werden.
Denition 18 (Codierungen von Tupeln und Listen).
Die Standard k-Tupelfunktionen
k
:N
k
N sind induktiv deniert durch
x
1
= x
x
1
, .., x
k+1

k+1
= x
1
, .., x
k

k
, x
k+1

Die Listencodierung

:N

N ist deniert durch


x
1
..x
k

= k, x
1
, .., x
k

Gelegentlich werden diese Funktionen mit


k
und

bezeichnet und es gilt =


2
.
Die meisten Eigenschaften der Standard-Tupelfunktion gelten auch f ur
k
und

.
Theorem 6.
1. Die Funktionen
k
:N
k
N und

:N

N sind f ur alle k N primitiv-rekursiv.


2. Die Funktionen
k
und

sind f ur alle k N bijektiv.


3. Die Umkehrfunktionen
k
i
:NN mit
k
i
= pr
k
i
(
k
)
1
sind f ur alle k N und
ik primitiv-rekursiv.
Dieses Theoremkann durch Induktion uber die Gr oe der Tupel k bewiesen werden.
Eine wichtige Konsequenz ist, da sich jede mehrstellige Funktion f:N
k
Ndurch eine
einstellige Funktion simulieren l at.
18
Theorem 7. Zu jeder primitiv-rekursiven Funktion f:N
k
N gibt es eine primitiv-
rekursive einstellige Funktion f

:NN mit der Eigenschaft f = f

k
.
Beweis: Wir w ahlen f

= f(
k
1
, ..,
k
k
). Dann ist f

primitiv rekursiv und es gilt f ur


alle x
1
, .., x
k
N
k
f

k
(x
1
, .., x
k
) = f(
k
1
, ..,
k
k
)x
1
, .., x
k

k
= f(x
1
, .., x
k
)

Die Tupelfunktionen liefern auch eine M oglichkeit, Funktionen mit mehrstelligen


Ein- und Ausgaben primitiv-rekursiv zu beschreiben. Wir werden von dieser M oglich-
keit sp ater gelegentlich Gebrauch machen.
Denition 19 (Mehrstellige primitiv-rekursive Funktionen).
Eine Funktion f:N
k
N
j
ist primitiv-rekursiv, wenn die zugeh orige einstellige
Funktion f

mit f

k
=
j
f primitiv-rekursiv ist.
Eine Funktion g:N

ist primitiv-rekursiv, wenn die zugeh orige einstellige Funk-


tion g

mit f

g primitiv-rekursiv ist.
Aufgrund dieser Denition k onnen wir alle berechenbare Funktionen auf Zahlen,
Tupeln und Listen als einstellige Funktionen ansehen, da die Unterschiede durch die
Standard-Tupelfunktionen ausgeglichen werden k onnen. Der Einfachheit halber wer-
den wir berechenbare Funktionen im folgenden ofter durch Gleichungen der Form
fx
1
, .., x
k
= y
1
, .., y
j
beschreiben und dabei sowohl die Funktionsklammern als
auch die Stelligkeit der Standard-Tupelfunktionen auslassen, sofern aus dem Kontext
klar ist, was gemeint ist.
3 Die Ackermannfunktion
Primitiv-rekursive Funktionen sind eine sehr m achtige Beschreibungsform f ur bere-
chenbare Funktionen und es ist hat sich herausgestellt, da es ausgesprochen schwierig
ist, Funktionen zu identizieren, die intuitiv berechenbar aber nicht primitiv rekursiv
sind. Daher war man lange Zeit der Ansicht, da primitiv-rekursive Funktionen als
Konzept ausreichen, um den intuitiven Begriff der Berechenbarkeit genau zu charak-
terisieren. Noch im Jahre 1926 stellte David Hilbert die Vermutung auf, dass alle bere-
chenbaren Funktionen primitiv-rekursiv seien.
Im gleichen Jahr gelang es jedoch seinen Sch ulern Wilhelm Ackermann und Gabri-
el Sudan unabh angig voneinander, Funktionen zu konstruieren,
5
die zwar total also
auf allen Eingaben deniert und offensichtlich berechenbar, jedoch nicht primitiv-
rekursiv waren. Die bekanntere der beiden Funktionen ist die 1928 publizierte Acker-
mannfunktion [1], obwohl Sudans Ergebnis allgemeiner war [2].
5
Interessant ist, da bisher alle total berechenbaren Funktionen, die nicht primitiv-rekursiv sind,
auf konstruierten Beispielen beruhen, die kein echtes nat urliches Gegenst uck in der Mathema-
tik besitzen. Es besteht daher nach wie vor die Vermutung, da alle berechenbaren mathe-
matischen Funktionen primitiv-rekursiv sein k onnten. Dies ist aber eine eher philosophische
Fragestellung, da auch k unstliche Konstruktionen mit einem gewissen Bekanntheitsgrad nach
einiger Zeit in die konventionelle Mathematik Einzug halten.
19
Sp ater wurden noch weitere Funktionen nach ahnlichem Bildungsprinzip entwi-
ckelt, die z.T. auch als Ackermannfunktionen bezeichnet werden.
6
Eine vereinfachte
Darstellung der urspr unglichen Ackermannfunktion stammt von der ungarischen Ma-
thematikerin R ozsa P eter [4]. Wir folgen hier ihrer Darstellung.
Denition 20 (Ackermann-Funktionen). Die Ackermann-FunktionenA
n
:NNsind
induktiv deniert durch
A
0
(x) =
_
_
_
1 falls x=0
2 falls x=1
x+2 sonst
A
n+1
(0) = 1
A
n+1
(x+1) = A
n
(A
n+1
(x))
Die groe Ackermannfunktion A:NN ist deniert durch A(x) = A
x
(x).
Mit einem einfachen Induktionsbeweis l asst sich zeigen, dass jede einzelne der
Ackermann-Funktionen A
n
primitiv rekursiv ist. Die Funktion A
0
ist offensichtlich
primitiv rekursiv und A
n+1
entsteht durch primitive Rekursion aus A
n
.
Theorem 8. Die Ackermannfunktionen A
n
:NN sind primitiv rekursiv f ur alle nN.
Damit ist intuitiv leicht einzusehen, da die groe Ackermannfunktion A total ist
und berechenbar sein mu. Da sie selbst nicht primitiv-rekursiv sein kann, liegt an
ihrem extremen Wachstumsverhalten, das man schon bei kleinen Eingaben erkennen
kann, wie die folgenden Berechnungen zeigen.
A
0
(x) = x+2 (x2)
A
1
(x) = 2x (x1)
A
2
(x) = 2
x
A
3
(x) = 2
(2
(2
...
2
)
)
. .
xmal
A
4
(0) = 1
A
4
(1) = 2
A
4
(2) = 2
2
= 4
A
4
(3) = 2
2
2
2
= 65536
A
4
(4) = 2
(2
(2
...
2
)
)
. .
65536mal
A
4
(5) = 2
(2
(2
...
2
)
)
. .
A4(4)mal
A(0) = 1
A(1) = 2
A(2) = 2
2
= 4
A(3) = 2
2
2
= 16
A(4) = 2
(2
(2
...
2
)
)
. .
65536mal
A(5) = A
4
(A
4
(....A
4
(1))))
. .
65536mal
= A
4
(A
4
(....A
4
(4))))
. .
65533mal
3.1 Die Ackermannfunktion ist nicht primitiv-rekursiv
Die Ackermannfunktionen A
n
sind, wie gezeigt, trotz ihres starken Wachstumsverhal-
tens immer noch primitiv rekursiv. Das noch erheblich st arkere Wachstums der groen
6
Funktionen dieser Art werden heute gerne als Benchmarks f ur Programmierspra-
chen/Compiler genutzt, um rekursive Prozeduraufrufe zu testen, da die zur Berechnung not-
wendige Schachtelungstiefe schnell zu einem Stackoverow f uhren kann. Dieser Ansatz geht
auf Sundblad [5] zur uck.
20
Ackermannfunktion A entsteht dadurch, da diese Funktion diagonal durch alle Acker-
mannfunktionen A
n
hindurchgeht und somit neben gr oer werdenden Argumenten
auch immer st arker wachsende Funktionen zur Berechnung des Funktionswertes ver-
wendet. Dadurch wird das Wachstumsverhaltens der groen Ackermannfunktion so ex-
trem, da keine primitiv-rekursive Funktion mithalten kann die groe Ackermann-
Funktion w achst st arker als jede primitiv-rekursive Funktion.
Ein pr aziser Beweis dieser Behauptung ist aufwendig, da eine Reihe von Indukti-
onsbeweisen und Lemmata uber das Monotonieverhalten der Ackermann-Funktionen
ben otigt werden. Wir geben daher ein einfaches intuitives Argument.
Eine gutes Klassikation der Komplexit at von Funktionen ist ihre (rekursive) Schach-
telungstiefe, also die Anzahl der ineinander verschachtelten Rekursionen. Jede primitiv-
rekursive Funktion hat eine feste Schachtelungstiefe und wir werden zeigen, da f ur die
groe Ackermannfunktion keine feste Schachtelungstiefe angegeben werden kann.
Denition 21 (Schachtelungstiefe primitiv-rekursiver Funktionen).
Die Schachtelungstiefe einer primitiv-rekursiven Funktion f ist induktiv deniert.
Jede Grundfunktion aus ( hat die Schachtelungstiefe 0.
Die Komposition von Funktionen mit maximaler Schachtelungstiefe n hat wieder-
um die Schachtelungstiefe n.
Die primitive Rekursion uber Funktionen der maximalen Schachtelungstiefe n be-
sitzt die hat die Schachtelungstiefe n+1.
Beispiel 22 (Schachtelungstiefe wichtiger Funktionen)
Die Addition konstanter Werte ist beschreibbar als ss..s
. .
kmal
.
Sie hat die Schachtelungstiefe 0.
Addition add, Vorg anger p und Signum-Funktion sign haben Schachtelungstiefe 1.
Multiplikation mul und Substraktion sub haben Schachtelungstiefe 2.
Exponentiation exp und Fakult atsfunktion fak haben Schachtelungstiefe 3.
Betrachten wir nun das Verhalten der Funktionen A
n
, so f allt auf, dass ihre Schach-
telungstiefe mit n w achst. Die Schachtelungstiefe von A
0
ist 2, wenn man das Kondi-
tional und den zugeh origen Ausdrucks aus dem Beweis von Theorem 1 verwendet, und
die Schachtelungstiefe von A
n+1
ist jeweils um 1 gr oer als die von A
n
.
Da die groe Ackermannfunktion A diagonal durch die Ackermannfunktionen hin-
durchgeht, bedeutet dies, da zur Berechnung des Wertes A(x) ein Ausdruck der Schach-
telungstiefe x+2 ben otigt wird, also die notwendige Schachtelungstiefe mit der Einga-
be w achst. Damit kann keine feste Schachtelungstiefe f ur die groe Ackermannfunktion
angegeben werden und deshalb kann A kann nicht primitiv-rekursiv sein.
Theorem 9. Die groe Ackermannfunktion ist nicht primitiv-rekursiv (AT!).
3.2 Wie kann man die Ackermannfunktion berechnen?
Die klare rekursive Beschreibung der groe Ackermannfunktion macht es leicht, einen
intuitiven Berechnungsmechanismus f ur diese Funktion anzugeben. Bei Verwendung
moderner funktionaler Programmiersprachen ist es sogar nahezu trivial, ein Programm
21
f ur die groe Ackermannfunktion anzugeben. In ML-Notation w urde solch ein Pro-
gramm wie folgt aussehen.
let rec A(n, x) =
if n=0 then if x=0 then 1 else if x=1 then 2 else x+2
else if x=0 then 1 else A(n-1,A(n,x-1))
let A(x) = A(x,x)
Die Berechnung von A(x) f uhrt dann zu einer schrittweisen Abarbeitung der Rekursion,
wobei die Verarbeitung von Rekursionsstacks durch den Compiler geregelt wird.
Die groe Ackermannfunktion kann jedoch auch im Kalk ul der rekursiven Funktio-
nen programmiert werden. Hierzu mu man das explizit beschreiben, was in modernen
Programmiersprachen der Compiler ubernimmt, n amlich die Verarbeitung des Berech-
nungsstacks der Ackermannfunktion. Wir wollen dies zun achst an einem Berechnungs-
beispiel f ur A(2) erl autern.
Beispiel 23 (Berechnung der Ackermannfunktion)
A(2) = A
2
(2)
= A
1
(A
2
(1))
= A
1
(A
1
(A
2
(0)))
= A
1
(A
1
(1)))
= A
1
(A
0
(A
1
(0)))
= A
1
(A
0
(1))
= A
1
(2)
= A
0
(A
1
(1)))
= A
0
(A
0
(A
1
(0)))
= A
0
(A
0
(1))
= A
0
(2)
= 4
A(2) 2, 2

1, 2, 1

1, 1, 2, 0

1, 1, 1

1, 0, 1, 0

1, 0, 1

1, 2

0, 1, 1

0, 0, 1, 0

0, 0, 1

0, 2

Die rekursive Abarbeitung der Denition der Ackermannfunktionen kann verein-


facht durch die Liste der vorkommenden Zahlen beschrieben werden, die wiederum
mithilfe der Standard-Tupelfunktion als nat urliche Zahl dargestellt wird. Anstelle von
A
2
(2) schreiben wir also 2, 2

, anstelle von A
1
(A
2
(1)) schreiben wir 1, 2, 1

usw.
Damit wird die Berechnung der Ackermannfunktion, wie auf der rechten Seite illus-
triert, durch eine Folge von Zahlen codiert, wobei die

Uberg ange zwischen diesen Zah-
len der rekursiven Denition der Ackermannfunktionen entsprechen. Die Berechnung
endet, wenn der Stack nur noch ein einziges Element, das Ergebnis, enth alt.
Wir wollen nun zeigen, da die Abarbeitungsfunktion eines Berechnungsstacks
f ur die Ackermannfunktionenals primitiv-rekursive Funktion beschrieben werden kann.
Nach Denition 20 mu diese Funktion folgende Eigenschaften besitzen.
wn0

= w1

An(0) = 1
w0 1

= w2

A0(1) = 2
w0 (x+2)

= w(x+4)

A0(x+2) = x+4
w(n+1)(x+1)

= wx(n+1) x

An+1(x+1) = An(An+1(x))
Dabei steht w f ur eine beliebige Liste nat urlicher Zahlen, w ahrend x und n einache
Zahlen sind. Durch die Verwendung der Standardtupelfunktion wird der gesamte Stack
als nat urlicher Zahl dargestellt und daher kann :NN eine feste Stelligkeit haben, ob-
wohl die Gr oe des Stacks sich st andig andert. Da die Standardtupelfunktion bijektiv ist
22
und primitiv-rekursive Umkehrfunktionenbesitzt, l at sich mittels Fallunterscheidung
und der Verwendung einfacher primitiv-rekursiver Funktionen programmieren und ist
somit selbst primitiv rekursiv.
Die Berechnung der groen Ackermannfunktion kann nun durch eine Iteration der
Abarbeitungsfunktion beschrieben werden. Es ist A(x) =
2
2
(
k
xx

, also der ei-


gentliche Inhalt des Stacks
k
xx

, wobei k die kleinste Zahl ist f ur die der Stack nur


aus einer einzigen Zahl besteht, also f ur die
2
1
(
k
xx

)=1 gilt.
Da die Iteration primitiv-rekursiver Funktionen primitiv-rekursiv ist, ist auch die
Berechnung von
k
xx

primitiv rekursiv. Der einzige Teil der Berechnung, der nicht


mit primitiv-rekursiven Mitteln beschrieben werden kann ist die Bestimmung der Zahl
k, also der Anzahl der Schritte bis zur Terminierung. Dies mu mit einem Suchproze
erreicht werden, der aber im Gegensatz zur beschr ankten Minimierung ohne vorge-
gebene Schrittzahlgrenze durchgef uhrt werden mu. Zwar l at sich durch Induktion
beweisen, da diese Suche terminieren mu, da in jedem -Schritt entweder die erste
bearbeitete Zahl im Stack oder die Anzahl der Zahlen kleiner wird, aber diese Erkennt-
nis reicht nicht aus, um die Schrittzahlgrenze im Voraus angeben zu k onnen. Man mu
die Suche also ohne Angabe einer Schrittzahlbegrenzung durchf uhren und dieser Pro-
ze ist, wie in Theorem 9 gezeigt, nicht mehr primitiv rekursiv. Diese Erkenntnis f uhrt
zu einer Erweiterung des Berechnungsmodells der rekursiver Funktionen, die wir im
folgenden Kapitel besprechen werden.
4 -rekursive Funktionen
Die Hinzunahme einer unbegrenzten Minimierung stellt eine echte Erweiterung des
Kalk uls der primitiv-rekursiven Funktionen dar. Eine unbegrenze Suche kann m ogli-
cherweise nicht zum Erfolg f uhren und liefert dann kein Ergebnis. Die hierdurch be-
schriebene Funktion ist also an dieser Stelle undeniert und somit eine partielle Funk-
tion. Anders als die primitiv-rekursiven Funktionen mu der so entstehende Kalk ul die
M oglichkeit undenierter Funktionsergebnisse mit einkalkulieren. Dies bedeutet, da
das Verhalten der in Denition 3 beschriebenen Operatoren Komposition und primitive
Rekursion f ur partielle Funktionen neu erkl art werden mu.
Die Komposition f(g
1
, .., g
n
):N
k
N ist deniert f ur eine Eingabe xN
k
, wenn
jedes g
i
hierauf deniert ist und ( g
1
( x), .., g
n
( x) ) zumDenitionsbereich von f geh ort.
Ansonsten ist sie undeniert.
Eine durch primitive Rekursion Pr[f, g] denierte Funktion h:N
k
N ist deniert
auf ( x, 0), wenn f auf x deniert ist und genau dann auf ( x, y+1) deniert, wenn
h( x, y) deniert ist und ( x, y, h( x, y)) zum Denitionsbereich von g geh ort. Man be-
achte, da damit h( x, y) nur dann deniert ist, wenn h( x, z) f ur alle z<y deniert ist.
F ur die unbegrenzten Minimierung f uhrt die Betrachtung partieller Funktione zu
folgender Denition.
Denition 24 (-Operator). Die Minimierung f:N
k
Neiner Funktion f:N
k+1
N
ist die eindeutig bestimmte Funktion h f ur die f ur alle xN
k
gilt
h( x) =
_
miny [ f( x, y)=0 falls dies existiert und alle f( x, i) f ur i<y deniert sind
sonst
23
In der Denkweise imperativer Programmiersprachen entspricht die Minimierung ei-
ner unbegrenzte Suchschleife. Wenn die Suche Terminiert, dann liefert sie die Anzahl
der Durchl aufe bis zum Abbruch dieser Schleife. Um h = f zu berechnen, w urde man
folgende Anweisungen verwenden.
z := 0; while f(x
1
,..,x
k
,z),=0 do z:=z+1; h := z
Im Gegensatz hierzu w urde die beschr ankte Minimierung wie folgt implementiert.
z := 0; while f(x
1
,..,x
k
,z),=0 and zy do z:=z+1; h:= z
Anstelle von h = f schreibt man gelegentlich auch h(x) =
z
[f(x, z)=0], wobei an
der Stelle von f(x, z) ein beliebiger Ausdruck uber den Variablen x und z stehen darf.
Funktionen die aus den Grundfunktionen durch Komposition, primitive Rekursion
oder Minimierung entstehen, heien -rekursiv oder kurz rekursiv.
Denition 25 ((-)rekursive Funktionen).
Die Menge R der (-)-rekursiven Funktionen ist deniert als ! =
_

n=0
!
n
. Dabei
sind die Klassen T!
i
induktiv wie folgt deniert.
!
0
= ( und
!
i+1
= !
i
f(g
1
, .., g
n
) [ nN, f, g
1
...g
n
!
i

Pr[f, g] [ f, g !
i
f [ f !
i

Ahnlich wie die formale Denition der Klasse T!in Denition 4 ist die obige De-
nition oft schwer zu handhaben. Meist ist die folgende Charakterisierung handlicher.
Korollar 26
1. Die Nachfolgerfunktion s ist -rekursiv.
2. Die Projektionsfunktionen pr
n
k
sind -rekursiv f ur alle nN und k 1..n.
3. Die Konstantenfunktionen c
n
k
sind -rekursiv f ur alle n, k N.
4. Die Komposition f(g
1
, .., g
n
):N
k
N der Funktionen f:N
n
N, g
1
, ..g
n
:N
k
N
ist -rekursiv f ur alle n, k N, wenn f, g
1
...g
n
-rekursiv sind.
5. Die primitive Rekursion Pr[f, g]:N
k
N zweier Funktionen f:N
k1
N und
g:N
k+1
N ist -rekursiv f ur alle k N, wenn f und g -rekursiv sind.
6. Die Minimierung f:N
k
N einer Funktion f:N
k+1
N ist -rekursiv f ur alle
k N, wenn f -rekursiv ist.
Durch die Hinzunahme des -Operators andert sich eigentlich nur wenig am Kon-
zept der rekursiven Funktionen. Die Analyse und Konstruktion -rekursiver Funktio-
nen ist ahnlich zu derjenigen der primitiv-rekursiven Funktionen, f ur die bereits eine
begrenzte Minimierung zur Verf ugung stand. Es entf allt nun die Notwendigkeit, eine
Obergrenze f ur die Suche im Voraus anzugeben. Daf ur mu man allerdings mit m ogli-
cherweise partiellen Funktionen und undenierten Funktionswerten umgehen. Wir wol-
len dies an einigen Beispielen erkl aren.
Beispiel 27 (Analyse -rekursiver Funktionen)
24
Wir wollen den Ausdruck f
2
= c
2
1
analysieren. Es ist
f
2
(x) =
_
miny [ c
2
1
(x, y)=0 falls y existiert und alle c
2
1
(x, i), i<y deniert
sonst
=
_
miny [ 1 = 0 falls dies existiert
sonst
=
Damit ist f
2
die nirgends denierte Funktion.
Wir betrachten f
3
= add. Es ist
f
3
(x) =
_
miny [ add(x, y)=0 falls y existiert (add ist total)
sonst
=
_
0 falls x = 0
sonst
Damit ist f
3
nur f ur x=0 deniert.
Wir betrachten f
4
= h, wobei h(x, y) =
_
0 falls x=y
sonst
. Dann ist
f
4
(x) =
_
miny [ h(x, y)=0 falls y existiert und alle h(x, i), i<y deniert
sonst
=
_
0 falls x = 0
sonst
Hier ist zu beachten, da zwar h(x, y) = 0 f ur x=y gilt, aber h(x, y) f ur 0<y<x
undeniert ist.
-rekursive Funktionen haben gegen uber den primitiv-rekursiven Funktionen den
Nachteil, da sie m oglicherweise partiell, also nicht f ur alle Eingaben deniert sind.
Primitiv-rekursive Funktionen sind dagegen total, terminieren also immer. Eine wich-
tige Unterklasse der -rekursiven Funktionen sind daher die Funktione, die total, aber
nicht notwendigerweise primitiv rekursiv sind.
Denition 28 (total-rekursive Funktionen).
Die Menge T Rder total-rekursiven Funktionen ist deniert als
T ! = f ! [ f total.
Es ist leicht zu sehen, da T! T ! ! gilt, da alle primitiv-rekursiven Operatoren
und Grundfunktionen auch bei der Denition der -rekursiven Funktionen verwendet
werden und alle primitiv-rekursiven Total sind. Da die drei Klassen nicht gleich sind,
kann man an zwei einfachen Beispielen sehen.
T! , = T !, da die groe Ackermannfunktion A total rekursiv, aber nicht primitiv-
rekursiv ist.
T !,=!, da es rekursive Funktionen wie z.B. f
3
= add gibt, die nicht total sind.
Damit ist T!eine echte Unterklasse von T ! und dies eine echte Unterklasse von !.
25
Die Klasse der total-rekursive Funktionen ist die Klasse, die aus Anwendersicht
die interessanteste w are, da sie alle berechenbare Funktionen enth alt, aber keine nicht-
terminierenden Berechnungen ber ucksichtigen mu. Leider ist es nicht m oglich, einen
Kalk ul oder eine Programmiersprache zu konstruieren, die genau die Klasse T ! er-
zeugt, denn die Menge der Programme f ur Funktionen aus T ! ist nicht aufz ahlbar.
Dies werden wir in einer der sp ateren Abhandlungen zeigen.
Rekursive Funktionen sind ein extrem m achtiger Mechanismus zur Beschreibung
berechenbarer Funktionen. Es hat sich herausgestellt, da sie genauso m achtig sind wie
die Turing-berechenbaren Funktionen. Ein formaler Beweis f ur diese Behauptung ist
aufwendig, da f ur jedes Modell eine Simulation durch das andere angegeben werden
mu. Wir geben daher (vorl aug) nur eine kurze Skizze des Beweises
Umzu zeigen, da rekursive Funktionen Turing-berechenbar sind (!T ), mu man
zeigen, da die rekursiven Grundfunktionen und Operationen Turing-berechenbar sind.
Turingmaschinenprogramme f ur die Grundfunktionen Nachfolger, Projektion und
Konstantenfunktionen sind leicht zu konstruieren. Auch haben wir gezeigt, da es leicht
ist, Komposition, Primitive Rekursion und -Operator durch Anweisungssequenzen in
imperativen Programmiersprachen zu repr asentieren. Da alle Computerprogramme auf
Turing-Maschinen simuliert werden k onnen, ist es m oglich Turingmaschinen f ur die
rekursiven Operationen zu konstruieren. Damit kann man f ur jede rekursive Funktion
f eine Turingmaschine konstruieren, indem man die Teilmaschinen entsprechend des
rekursiven Ausdrucks f ur f zusammensetzt.
Umzu zeigen, da Turing-berechenbare Funktionen rekursiv sind (T !), geht man
ahnlich vor wie bei der Berechnung der Ackermannfunktion durch rekursive Funktio-
nen in Abschnitt 3.2. Wir codieren Kongurationen, also Tupel von Worten als Zah-
lentupel, indem wir jedes Symbol durch seine Nummer im Alphabet repr asentieren
und anschlieend die Zahlenliste mit der Standard-Tupelfunktion in eine Zahl umwan-
deln. Anschlieend simulieren wir die Kongurations uberg ange, die sich aus dem Pro-
gamm der Turingmaschine ergeben durch eine primitiv-rekursive

Uberf uhrungsfunkti-
on . Diese wird dann iteriert bis eine Endkonguration erreicht ist. Hierzu verwenden
wir eine primitiv-rekursive Testfunktion f, welche identizert ob
k
eine Endkon-
gurationen liefert und die unbeschr ankte Minimierung f ur die Suche nach der ersten
Nullstelle von f. Wenn diese Suche terminiert, dann liefert die Endkonguration das
Ergebnis der Berechnung.
Theorem 10. ! = T , d.h. die Klasse der rekursiven Funktionen ist identisch mit der
Menge der Turing-berechenbaren Funktionen.
Theorem 10 und sein Beweis haben zwei wichtige Aspekte. Zum einen ist gezeigt,
da beide Modelle Turingmaschine und rekursive Funktionen sich gegenseitig si-
mulieren k onnen. Deswegen ist es m oglich, in Beweisen -rekursive Funktionen als
Unterprogramme von Turingmaschinen einzusetzen, wenn dies einfacher ist als die
direkte Konstruktion. Es reicht ja zu wissen, da eine Umwandlung m oglich ist, ohne
da man sie explizit ausf uhren mu. Zum anderen wurde im Beweis von T !nur eine
einzige Minimierung eingesetzt, um die Anzahl der Schritte bis zur Terminierung zu
bestimmen, w ahrend alle anderen Komponenten primitiv rekursiv sind.
26
Dies bedeutet, da rekursive Funktionen im Prinzip nicht mehr als eine einzige Mi-
nimierung ben otigen und ansonsten mit primitiv-rekursiven Konstrukten auskommen
k onnen. In anderen Worten: jede berechenbare Funktionen k onnen mit einer einzigen
unbegrenzten Schleife programmiert werden. Diese Erkenntnis ist unter dem Namen
Kleene Normalform Theorem bekannt geworden.
Theorem 11 (Kleene NormalformTheorem). F ur jede berechenbare Funktion h kann
man primitiv-rekursive Funktionen f und g konstruieren, so da h(x) = g(x, f(x)).
Beweis: Wir betrachten die Simulation der Turingmaschine f ur h durch -rekursive
Funktionen. Die Funktion g mit g(x, k) berechnet die Iteration
k
(x) der Kongu-
rations uberg ange. f ist die Funktion, welche die Terminierung von
k
(x) charak-
terisiert und damit berechnet f berechnet die Anzahl der Schritte bis zur Termi-
nierung. Damit liefert g(x, f(x)) das Ergebnis zum Zeit der Terminierung.
Literatur
1. Wilhelm Ackermann. Zum hilbertschen Aufbau der reellen Zahlen. Mathematische Annalen,
99, 1928. 19
2. Christian Calude and Solomon Marcus. The rst example of a recursive function which is not
primitive recursive. Historia Mathematica, 6:380384, 1979. 19
3. Richard Dedekind. Was sind und was sollen die Zahlen? 1888. 1
4. R ozsa P eter. Die beschr ankt-rekursiven funktionen und die ackermannsche Majorisierungs-
methode. Publicationes Mathematicae Debrecen, 4:362375, 1956. 20
5. Yngve Sundblad. The ackermann function. a theoretical, computational, and formula mani-
pulative study. BIT - numerical mathematics, 11:107119, 1971. 20
27