| Wieviele Funktionen `g: NN -> {0,1}` existieren? | Unendlich viele |
| `>` | |
| Wieviele Programme existieren? | Unendliche viele |
| `=` | |
| Wieviele natürliche Zahlen existieren? | Unendlich viele |
Wir benötigen ein "Handwerkszeug" um verschiedene Stufen der Unendlichkeit unterscheiden zu können.
| endlich | `|A| < omega` |
| unendlich, aber abzählbar | `|A| = omega` |
| unendlich, nicht abzählbar | `|A| > omega` |
Sprich: Einfach abzählen.
Sei `A` eine abzählbare Menge, dann ist jede Teilmenge `B` von `A` abzählbar oder endlich. bsp-Q abzählen- TODO grafik einfügen
Sei `A` eine überabzählbare Menge, so ist jede Obermenge von `A` ebenfalls überabzählbar.
TODO bild Wir konstruieren eine Funktion `f: NN -> {0,1}` entlang der Diagonalen.
Offensichtlich ist ist `f(n) in A`, kommt aber in der Abzählung nicht vor, denn gäbe es ein `g` mit `g_i = f(n)`, so müsste gelten, dass `g_i(i) = f(i) = not g_i(i)`. Widerspruch! `=> {g:NN -> {0,1}}` ist überabzählbar. Beobachtung: Wir können nur abzählbar viele Dinge (Automaten, mathematische Funktionen, Sprachen) syntaktisch repräsentieren. Damit können wir sagen: "Es existieren überabzählbar viele Funktionen, die wir nicht syntaktisch repräsentieren bzw. berechnen können.
... bilden eine syntaktische Repräsentation einer Sprache (z.B. Programmiersprache, syntaktische Ausdrücke, XML, HTML, ...).
| `V` | Menge der Variablen (endlich) |
| `Sigma` | endliche Menge, sog. terminales Alphabet (die Operatoren), wobei `V sub Sigma = 0` |
| `P` | Produktionen/Regeln |
| `S` | Startvariable |
Sei `G=(V,Sigma,P,S)` eine Grammatik und seien `u,v in (V uu Sigma)^**`:
07-07-12
Die von endlichen Automaten akzeptierten Sprachen sind genau die Sprachen, die durch reguläre Ausdrücke spezifiziert werden können. Diese Sprachen werden als reguläre Sprachen bezeichnet.
`01^"*"+1 = (0(1^"*"))+1`
-> der Ausdruck ist von der Form
| r | = | `r_1` | + | `r_2` |
| `01^"*"` | `1` |
TODO bild
Beachten Sie, dass die Notwendigkeit, die Zustandsmengen verschiedener Automaten disjunkt zu halten, uns davon abhält den gleichen NEA für `r_2` und `r_5` zu benutzen, obwohl es sich eigentlich um den selben regulären Ausdruck handelt. Um einen NEA `r_4 = r_5**` zu konstruieren benutzen wir die Hüllenbildung. Zunächst sind Zustände `q_7` und `q_8` zu erzeugen, die die Rollen von `q_0` (Anfangszustand) und `f_0` (Endzustand) übernehmen. TODO bild Dann wird die Konstruktion für `r_1 = r_3 r_4` verwendet. TODO bild Abschliessend gilt: `r = r_1 + r_2`
Nachdem wir nun verschiedene Hilfsmittel zur Repräsentation regulärer Mengen kennengelernt haben, werden wir uns nun mit der Fragestellung in Bezug auf spezielle gegebene Sprachen `L` beschäftigen. Welche Fragen sind in diesem Zusammenhang von Interesse?
Das Pumping-Lemma ist ein mächtiges Hilfsmittel um zu zeigen, dass gewisse Sprachen nicht regulär sind. Es hilft ebenso um gewisse Aussagen über EA zu beweisen (z.B. ob die jeweils akzeptierte Sprache endlich oder unendlich ist, sprich zyklen existieren). Sei `A = (Q,Sigma,delta,q_0,F)` ein deterministischer endlicher Automat mit `n = |Q|`. Betrachten sie eine Eingabe, die aus `n` oder mehr Zeichen besteht. `a_1 a_2 ... a_m` `m >= n` für `i = 1,2,...,m` sei `delta(q_0,a_1a_2...a_i) = q_i` es kann nicht sein, dass alle `n+1` Zustände `q_0,q_1,...,q_n` verschieden sind, da es nur `n` Zustände gibt. => es gibt `j,k in NN` mit `0 <= j < k <= n`, sodass `q_j = q_k`. TODO bild da `j < k` ist die Länge von `a_(j+1)...a_k >= 1` da `k < n` ist die Länge von `a_(j+1)...a_k <= n`
Wenn `a_1...a_j a_(j+1)...a_k a_(k+1)...q_m in L(A)`, dann `a_1...a_j a_(k+1)...a_m in L(A)` und `a_1...a_j(a_(j+1)...a_k)^i a_(k+1)...a_m in L(A)`. `AAi>=0`
Das Pumping-Lemma besagt nur, dass eine reguläre Menge, wenn sie eine lange Zeichenkette `Z` enthält, auch unendlich viele Zeichenketten der Form `uv^iw` enthält. Es besagt aber nicht, dass jede genügend lange Zeichenkette in einer regulären Menge von der Form `uv^iw` für ein grosses `i` ist.
Frage: Ist die Sprache `L={0^(k^2)|k in NN, k>=1}, die aus allen aus Nullen zusammengesetzten Zeichenketten, deren Länge eine Quadratzahl ist, regulär?
Nehmen wir an, `L` wäre regulär: `n` sei die ganze Zahl aus dem Pumping-Lemma `z` sei `0^(n^2)`. Klarerweise ist `|z| > n`. Nach dem Pumping-Lemma kann `0^(n^2)` geschrieben werden als `uvw`, wobei `1 <= |v| <= n` und `uv^iw in L` für alle `i`. Dies gilt natürlich auch für ein konkretes `i=2`! ABER: ToDo bild2 -> Die Länge von `uv^2w` liegt echt zwischen `n^2` und `(n+1)^2` und ist somit kein perfektes Quadrat. -> Widerspruch D.h. die Annahme, dass `L` regulär sei ist falsch. => L ist nicht regulär
Die kontextfreien Sprachen sind, wie die regulären Mengen, von großer Bedeutung bei der Definition von Programmiersprachen. z.B. Beschreibung korrekt geklammerter Ausdrücke begin-end Strukturen in Programmiersprachen -> durch reguläre Ausdrücke nicht darstellbare Konstrukte. Kontextfreie Grammatiken (kfG) sind vergleichbar mit der bereits bekannten Backus-Naur-Form (BNF) zur Beschreibung von Programmiersprachen.
zur Definition von Grammatiken, Satz und Satzform siehe Abschnitt 1.1.2.4. :kontextfreie Grammatik: Eine Grammatik `G = (V,Sigma, P, S)` heisst kontextfrei, wenn gilt `P sube V xx (V uu Sigma)^** ` und jede Produktion der Grammatik die Form `A -> w` hat, wobei `A in V` und `w in (V uu Sigma)^**`. :kontextfreie Sprache: Eine Sprache `L` heisst kontextfrei, wenn es eine kfG gibt, die `L` erzeugt (`L=L(G)`). Wir werden folgende Konventionen in Bezug auf Grammatiken benutzen (Variablen, Terminal und Startsymbole):
Die Ableitung der Sätze einer Grammatik läßt sich auch graphisch in Form eines Baumes darstellen. Die so dargestellte Struktur der Wörter einer Sprache ist insbesondere für die Compilierung von Programmiersprachen von Bedeutung.
ToDo Beispiel3
Unter Umständen kann ein Wort einer Sprache auf unterschiedlichen Wegen mittels der angegebenen Grammatik abgeleitet werden.
ToDo Bsp4
Eine kontextfreie Grammatik, in der es ein Wort mit mehr als einem Ableitungsbaum gibt, heißt mehrdeutig. Eine kfS, für die jede kfG mehrdeutig ist, heißt ererbt mehrdeutige kfS (inherently ambigous). Wird im Rahmen einer Ableitung bei jedem Schritt eine Produktion auf die linksstehende Variable angewendet, so sprechen wir von einer Linksableitung. Wird die Produktion bei jedem Schritt auf die rechtsstehende Variable angewendet, so sprechen wir von einer Rechtsableitung.
Linksableitung zu (1) `A -> A + A -> a + A -> a + A * A -> a + b * A -> a + b * c`
Rechtsableitung zu (1) `A -> A + A -> A + A * A -> A + A * c -> A + b * c -> a + b * c`
So wie die regulären Ausdrücke den endlichen Automaten Äquivalent sind, haben auch die kfG ein Automaten-Gegenstück, die sogenannten Kellerautomaten. Allerdings ist hier die Äquivalenz leider nicht gleich ausgeformt wie das bei den endlichen Automaten der Fall war. Kellerautomaten sind nichtdeterministische Konstrukte (die deterministische Variante akzeptiert nur eine Teilmenge der kfS - diese umfasst allerdings die Syntax der meisten Programmiersprachen).
ToDo Bild Das beschriebene Gerät akzeptiert eine Eingabe, wenn ebi der Bearbeitung des letzten Zeichens der Tellerstapel leer wird. Ist der Stapel einmal leer, so können keine weiteren Bewegungen gemacht werden.
Ein Kellerautomat `A` über einem Alphabet `Sigma` besteht aus
Sei `A = (Q, Sigma, Gamma, delta, q_0, z_0, F)` ein Kellerautomat. Ein Wort `delta in Sigma^** Q Gamma^**` heisst Konfiguration von `A`.
`epsilon q_0 z_0` heisst Startkonfiguration von `A`. das heisst `epsilon` = ich stehe ganz vorn auf `q_0` und habe da `z_0` stehen Für `gamma = omega q y alpha` mit `omega in Sigma^** , q in Q, y in Gamma, alpha in Gamma^** ` und `x in Sigma uu {epsilon}, beta in Gamma^**` mit `((q,x,y)(p,beta)) in gamma` heißt `gamma' = omega x p beta alpha` eine Folgekonfiguration von `gamma` in `A`, wir schreiben `gamma |-> A gamma'`.
Sei `A=(Q, Sigma, Delta, delta, q_0, z_0, F)` ein Kellerautomat. Wir nennen `L(A) = { w in Sigma^** | q_0z_0 |-> w q alpha, q in F}` die (über den Endzuständen) akzeptierte Sprache zu `A`.
Wir nennen `N(A) = { w in Sigma^** | q_0z_0 |-> w q epsilon, q in Q}` die mit leerem Keller akzeptierte Sprache von `A`.
Dies ist gleichbedeutend mit:
Ein Kellerautomat `A=(Q, Sigma, Gamma, delta, q_0, z_0, F)` heißt deterministisch, wenn für `q,q_1,q_2 in Q, x in Gamma, a in Sigma` und `alpha_1, alpha_2 in Gamma^**` gilt:
`((q,a,x),(q_1,alpha_1)) in delta ^^` `((q,a',x),(q_2,alpha_2)) in delta`
`=> q_1 = q_2 ^^ alpha_1=alpha_2`, wenn `a=a'`.
Man sieht leicht, dass für einen deterministischen Kellerautomaten für jede Konfiguration `delta` höchstens eine Folgekonfiguration `delta'` existiert.
Die von (nichtdeterministischen) Kellerautomaten akzeptierten Sprachen sind genau die kontextfreien Sprachen.
Jede kontextfreie Sprache wird von einem Kellerautomaten mit leerem Keller akzeptiert. Im Gegenschluß gilt: Jede von einem Kellerautomaten akzeptierte Sprache ist kontextfrei.
Eine Menge ist hinsichtliche einer bestimmten Operation abgeschlossen, wenn das Ergebnis wieder Element der Menge ist. So sind z.B. die Addition und Multiplikation über den natürlichen Zahlen abgeschlossen, die Division jedoch nicht.
Die kontextfreien Sprachen sind abgeschlossen unter:
Für jede kontextfreie Sprache `L` (repräsentiert durch eine kontextfreie Grammatik oder einen Kellerautomaten) ist entscheidbar (grundsätzlich lösbar), ob
Für ein Wort `omega in Sigma^**` und eine kontextfreie Sprache `L` ist entscheidbar, ob `omega in L` gilt.
Viele Probleme, die für reguläre Sprachen entscheidbar sind, sind bereits für kontextfreie Sprachen unentscheidbar.
Diese Fragen können nicht in jedem Fall geklärt werden.
Es wird an dieser Stelle die Turing-Maschine als einfaches mathematisches Modell für einen Computer eingeführt. Trotz ihrer Einfachheit modelliert die Turing Maschine die durch einen Allzweck-Computer gegebene Berechenbarkeit.
In einem engen Zusammenhang mit dem hier auftretenden Begriff der "Berechenbarkeit" steht auch der Begriff des "Algorithmus". Eine intuitive Vorstellung von einem Algorithmus kann vorausgesetzt werden -- doch was versteht man formal darunter?
Die Turing-Maschine ist ein anerkannter Formalismus für die Beschreibung von Algrorithmen. Das zugrunde liegende Modell wurde 1936 von Alan Turing in der hier beschriebenen Variante vorgestellt.
TODO Bild
Abhängig vom gelesenen Bandsymbol und dem Zustand der endlichen Kontrolle kommt es zu folgenden
| `M` | Maschine |
| `Q` | Zustände |
| `Sigma` | Eingabesymbole (Teilmenge der erlaubten Bandsymbole ohne `B`) |
| `Delta` | erlaubte Bandsymbole |
| `delta` | Übergangsfunktion `Q x Sigma -> Q x Delta x {LR}` |
| `q_0` | Anfangszustand `in Q` |
| `B` | Blank |
| `F` | Menge der Endzustände (`F sube Q`) |
`M` ist ein Tripel `<alpha_1, q, alpha_2> in Gamma^** x Q x Gamma^**` geschrieben `alpha_1 q alpha_2` und beschreibt die Situation, dass sich auf dem Arbeitsband vom `M` die Zeichenkette `alpha_1 alpha_2` befindet (gefolgt von Blanks `B`), `M` den Zustand `q` innehat und der Kopf von `M` das erste Zeichen von `alpha_2` liest. (`alpha_1 alpha_2` kann Blanks `B` enthalten!) Im Falle `alpha_2 = sigma` (leer) bedeutet das, dass sich der Kopf von `M` über einem Blank `B` befindet. ToDo Bild
Sei `alpha_1 q alpha_2` die aktuelle Konfiguration mit `alpha_1 = A_1 A_2 ... A_i-1` und `alpha_2 = A_i A_i+1 ... A_n`.
Wir nehmen an, dass der Schreib-/Lesekopf das am weitesten links stehende Symbol von `alpha_2` liest bzw. falls `alpha_2 = sigma` ein Blank `B` liest.
Sei nun `x_1 x_2 ... x_(i-1) q x_i x_(i+1) ... x_n` eine Zustandsbeschreibung und `delta ( q, x_i ) = ( p, y, L )`.
`x_1 x_2 ... x_(i-1) q x_i x_(i+1) ... x_n |-> x_1 x_2 ... x_(i-1) y p x_(i+1) ... x_n`
Stehen zwei Konfigurationen vom `M` in Relation `|->_M`, so können wir sagen, dass die zweite Konfiguration aus der ersten mittels einer Bewegung folgt. Resultiert eine Zustandsbeschreibung aus einer anderen durch eine endliche Anzahl von Bewegungen, so stehen diese beiden Zustandsbeschreibungen in der Relation `|->_M` (da meist klar ist, welche Macshine betrachtet wird, kann `_M` auch weggelassen werden - wir schreiben `|->` statt `|->_M` und `|->^**` statt `|->_M`.
Als von `M` akzeptierte Sprache `L(M)` bezeichnet man die Menge der Wörter aus `Sigma^**`, die `M` veranlassen in einen Endzustand überzugehen.
Dazu wird das entsprechende Wort linksbündig auf das Eingabeband geschrieben und die Turing-Maschine mit dem Kopf auf dem ersten Zeichen des Eingabewortes im Zustand `q_0` gestartet.
D.h. die von `M = (Q, Sigma, Gamma, delta, q_0, B, F)` erkannte Sprache `L(M) = { omega | omega in Sigma^** ^^ q_0 omega |-> alpha_1 p alpha_2` für ein `p in F` und `alpha_1, alpha_2 in Gamma^**}`
Zu beachten ist, dass die Turing-Maschine
ToDO Ergänzung
Aus der Definition von endlichen Turing-Maschinen folgt, dass die Menge aller üiberhaupt möglichen Turing-Maschinen aufzählbar sein muß. Man kann damit zeigen, dass jede Turing-Maschine einer rekursiv aufzählbaren formalen Sprache zugeordnet werden kann und umgekehrt.
In den letzten Kapiteln haben wir drei Familien formaler Sprachen kennengelernt:
Abhängig von den Einschränkungen, die an die Grammatik gestellt werden, können wir ebenfalls Sprachfamilien unterscheiden.
Eine Sprache `L sube Sigma^** ` heisst Sprache vom Typ `i` (`i=0,1,2,3`), wenn es eine Typ-i-Grammatik gibt, die `L` erzeugt.
In den folgenden Abschnitten werden die einzelnen Sprachfamilien noch genauer charakterisiert.
Die stärksten Restriktionen hatten wir an Grammatiken gestellt, die die regulären Sprachen erzeugen. Diese Grammatiken werden als reguläre Grammatiken oder auch als Typ-3-Grammatiken bezeichnet.
| `A -> sigma|omega|omega B|` | rechts-linear |
| `A -> sigma|omega|B omega|` | links-linear |\\ |
wobei `omega in Sigma^** ^^ A,B in V`
Die Produktionen einer kontextfreien Grammatik sind ein wenig allgemeiner:
`A -> alpha | A in V, alpha in (V uu Sigma)^** `
`A -> aXb`
`X -> abX | epsilon`
Bei den kontextsensitiven Sprachen ist es zulässig, dass auf der linken Seine einer Produktion sowohl Variablen als auch Terminale stehen.
Bei den Typ-0-Grammatiken werden dann schließlich keine Einschränkungen mehr an die Produktionen gestellt, außer dass aus dem leeren Wort nichts erzeugt werden darf.
Die erzeugten Sprachen entsprechen den von Turing-Maschinen erkannten Sprachen sowie den rekursiv aufzählbaren Sprachen.
AbaaC -> sigmaAbaa -> bbaa
Der Erzeugungsprozeß mus mit einem Startsymbol beginnen. Diese Grammatiken werden auch als Semi-Thui-System bezeichnet.
Typ 0 == Turing-Maschine
Typ 1 == kontextsensitiv
Typ 2 == Kellerautomat / kontextfrei
Typ 3 == endliche Automaten / reguläre Ausdrücke
Al Chwerizmi ~ 700 - 850
Aufgabensammlung für Kaufleute und Testamentsvollstrecker -> liber algorithmi
Alle Algorithmen haben unabhängig von wechselnden Notationen und Mechanismen zwei gemeinsame Eigenschaften:
Eine Eigenschaft von Algorithmen, an der man aus theoretischen wie praktischen Gründen interessiert ist, ist die Terminierung:
Der Algorithmus kommt in endlich vielen Schritten zu einem Ende ("terminierender Algorithmus").
Unter Determinismus eines Algorithmus ist zu verstehen, dass die Reihenfolge des Ablaufes der Einzelschritte des Algorithmus eindeutig vorgeschrieben ist.
Dieser gerne mit der Effektivität verwechselte Begriff beschreibt mit welchem Aufwand ein Algorithmus eine Aufgabe löst. Dabei wird der Aufwand möglicherweise in der Anzahl der benötigten Rechenschritte oder in der Belegung von Speicher gemessen. Die Effizienz ist lediglich eine praktische Frage -- allerdings eine sehr wichtige!
Grundsätzlich sind folgende Fragestellungen von Interesse:
Diese Fragestellungen beziehen sich auf die Berechenbarkeit von Problemen, auf die Theorie von Programmiersprachen sowie auf die Komplexität von Algorithmen. Dabei stellt sich immer wieder die Frage, wie sichein Computer als formales System beschreiben läßt. Insofern ist etwa zu klären, in wie weit formale Ansätze (Turing
ToDo complete
Ansicht: Man kann für jedes Problem zeigen, dass es entweder lösbar ist oder nicht.
f(Problem) -> {lösbar, unlösbar}
Gödel - Hilbert 1931 "Mathematikerstreit"
Möchte man beweisen, dass zu einem bestehenden Problem kein Algorithmus zu dessen Lösung existiert, so muss man den Begriff Algorithmus formalisieren.
Verwendet man das Konzept der Turing-Maschine als Modell zur formalen Beschreibung von Algorithmen, so ist jedes Problem dann algorithmisch lösbar, wenn es als Turing-Maschine dargestellt werden kann.
Computer sind äquivalent zur universellen Turing-Maschine `U`, d.h. zu einer Turing-Maschine, die jede andere Turing-Maschine `T` simlulieren kann.
ToDo Bild1
`U` ist eine abstrakte Beschreibung für jeden Computer.
`U` simuliert `T`.
Es gibt noch andere Beschreibungsmöglichkeiten von Algorithmen, etwa rekursive Funktionen, die sich aus einfachen, offensichtlich berechenbaren Funktionen bilden lassen.
Es besteht daher nach Alonzo Church und Alan Turing eine starke Evidenz (ohne dass ein streng mathematischer Beweis möglich wäre!) dafür, dass nicht nur die oben genannten Möglichkeiten der Formalisierung von Algorithmen gleichwertig sind und zu denselben Ergebnissen über die Berechenbarkeit von Problemen führen, sondern dass dies allgemein für alle im intuitiven Sinn vernünftigen Formalisierungen gilt.
Wenn ein Problem nicht durch eine Turing-Maschine gelöst werden kann, so ist es überhaupt nicht algorithmisch lösbar.
Eine Funktion `f(x)` heißt berechenbar, wenn es einen Algorithmus gibt, der bei gegebenem `x` das Ergebnis `f(x)` liefert.
oder alternativ:
Ist eine Menge `M` gegeben, so heißt `M` entscheidbar, wenn es einen Algorithmus gibt, der für jedes vorgegebene Element `x` als Ergebnis die Aussage liefert, ob `x` in `M` enthalten ist oder nicht.
Vermutung: nicht jede Funktion ist berechenbar
1. Die Menge aller Funktionen ist überabzählbar.
Ein Algorithmus muss wegen der Abbildung auf eine Turing-Maschine in jedem Fall durch ein Alphabet A mit einem endlichen Zeichenvorrat und einer endlcihen Zeichenfolge dargestellt werden können. (Bei TM reicht sogar A={0,1})
`A^** ` umfasst abzählbar unendlich viele Zeichenreihen
=> Zeichenreihen, die TM repräsentieren < `A^** `
=> { alle TM } ist abzählbar
jede TM entspricht einer Funktion
2. die durch TM repräsentierten (d.h., die berechenbaren) Funktionen sind abzählbar.
Aus 1. und 2. folgt: - Es muss nicht berechenbare Funktionen geben - die Menge der nicht berechenbaren Funktionen ist überabzählbar (d.h. es gibt mehr nicht berechenbare als berechenbare Funktionen!!)
Es wird nicht nur behauptet, es gäbe Probleme, zu deren Lösung noch kein Algorithmus bekannt sei, sondern es wird die stärkere Aussage gemacht, dass deshal kein lgorithmus zur Lösung dieser Probleme gefunden werden konnte, weil ein solcher grundsätzlich nicht existiert.
Frage:
Gibt es einen Algorithmus, mit dessen Hilfe man für ein beliebiges Programm `P` bestimmen kann, ob es mit den beliebigen Eingabedaten `D` jemals stoppen wird oder nicht?
Annahme: Es existiert ein Algorithmus zur Lösung des Halteproblems.
ToDo Bild2
Nun wird das Programm TEST1 mit dem Programmtext von TEST1 als Eingabe aufgerufen.
Nimmt man an, TEST1 stoppt, so folgt, dass TEST1 nicht stoppt und umgekehrt.
=> ToDoWiderspruch
Es ist somit bewiesen, dass das Halteproblem nicht berechenbar ist.
Die zum Beweis der Nichtberechenbarkeit des Halteproblems verwendete Technik des Beweises durch Widerspruch wird in diesem Zusammenhang häufig verwendet.
Neben dem Halteproblem gibt es eine ganze Reihe weiterer nicht berechenbarer Probleme, so z.B. das Äquivalenzproblem.
Fragestellung: Lösen zwei Programme dieselbe Aufgabenstellung?
Ein Vergleich von Halteproblem und Äquivalenzproblem zeigt, daß es zwei Klassen von Nichtberechenbarkeit gibt.
/ \ / \ Halteproblem Äquvalenzproblem | | Prog. stoppt in auch bei direkt vielen Fällen ersichtlicher | Äquivalenz keine partiell nicht maschinelle berechenbar Überprüfbarkeit
Die primitiv rekursiven Funktionen entstehen aus einigen einfachen Grundfunktionen über einem beliebigen Alphabet, welche man endlich oft anwendet. Da jedes Alphabet definitionsgemäß auf die natürlichen Zahlen mit Null abbildbar ist, genügt es `NN_0` zu betrachten.