Stichpunktezettel fürs Tutorium Moritz und Dorian 18. November 2009 1 Chomskys Erstschlag 1.1 Reguläre Sprachen und Grammatiken Aufgabe 1. Wie sieht die Sprache zu den folgenden Grammatiken aus? 1. G = ({S}, {a, b}, P, S) mit ( P := ) S → Sb S→a 2. G = ({S, A, B, C}, {a, b, c}, P, S) mit P := S → Aa|Bb|Cc|b A → Ba|Cb|a B → Bb|b C→c Aufgabe 2. Was wäre eine mögliche Grammatik für die folgenden Sprachen? 1. L = {a3 bn : n ∈ N∗ } 2. L = {an mod 2 bn : n ∈ N∗ } Lemma 1 (Pumping Lemma). Zu jeder regulären Sprache L gibt es eine Zahl `, so dass sich alle Wörter x ∈ L mit |x| ≥ ` in drei Teilwörter x = uvw zerlegen lassen, wobei gilt: 1. v 6= 2. |uv| ≤ ` 3. ∀i ≥ 0 : uv i w ∈ L 1 Das kleinste ` wird Pumping-Zahl von L genannt. Bemerkung. Das Pumping-Lemma liefert lediglich ein notwendiges, jedoch kein hinreichendes Kriterium für reguläre Sprachen. Wenn eine Sprache das Pumping-Lemma nicht erfüllt, ist sie nicht regulär, andernfalls ist sie vielleicht regulär. Aufgabe 3. Welche der folgenden Sprachen sind regulär? 1. L = {an : n ∈ N} 2. L = {3n10 : n ∈ N} (intuitiv: jede dezimal kodierte Zahl, die durch 3 teilbar ist) 3. L = {an bn : n ∈ N} 4. L = {ap : p ist prim} 2 Fermat-Test.2 Wir erinnern uns an den Fermat’schen Primzahltest von letzter Woche. ja Wähle ein a Ist a N −1 „vielleicht prim“ ≡1 mod N ? nein „zusammengesetzt“ Abbildung 1: Primzahltest nach Fermat Die Idee des Algorithmus war, dass aus dem kleinen Satz von Fermat ∀a < N, N prim ⇒ aN −1 ≡ 1 mod N folgte, dass ∃a < N : aN −1 6= 1 mod N falls N nicht prim ist. Wir möchten nun untersuchen, wie sinnvoll dieser Test ist, d. h. wie wahrscheinlich es überhaupt ist, auf diese Weise eine zusammengesetzte Zahl zu erkennen. Lemma 2. Falls ein a existiert, das relativ prim zu N ist und es gilt aN −1 6= 1 mod N , dann gibt es mindestens N/2 viele Zahlen für die diese Aussage ebenfalls gilt. 2 Beweis. Wähle ein a für das aN −1 6= 1 mod N . Der Schlüssel in diesem Beweis ist die Erkenntnis, dass für alle b < N , die den Fermat-Test bestehen (d. h. bN −1 ≡ 1 mod N ), die Zahlen a · b nicht bestehen: (a · b)N −1 ≡ aN −1 · bN −1 ≡ aN −1 6= 1 mod N Im Beweis der Satzes von Fermat hatten wir in der letzten Woche gesehen, dass die Funktion f (x) = a · x nur eine Permutation der Zahlen vornimmt. Deshalb sind für verschiedene b die Zahlen a · b unterschiedlich. Also gibt es mindestens so viele Zahlen, die den Test nicht bestehen, wie solche, die ihn bestehen. Daraus folgt direkt, dass für „gewöhnliche“ zusammengesetzte Zahlen die Wahrscheinlichkeit für das richtige Ergebnis bei mindestens 1/2 liegt. Da der Algorithmus aber auch keine falschen Aussagen macht, kann man ihn mehrmals ausführen, wobei sich die Wahrscheinlichkeiten multiplizieren. Bei der i’ten Iteration wäre die Wahrscheinlichkeit für eine Fehleinschätzung höchstens 1/2i . Leider gibt es auch Zahlen, für die kein a existiert, das relativ prim zu N ist, und für das aN −1 6= 1 mod N gilt, falls N keine Primzahl ist. Diese Zahlen werden„Carmichael“Zahlen genannt und sind äußerst selten; 561 ist die erste Carmichael-Zahl. 3 Effiziente Potenzierung Um den Fermat-Test effizient durchführen zu können, brauchen wir eine schnelle Exponentiationsroutine. Der naive Ansatz um ab zu berechnen wäre |a · a ·{z. . . · a} b mal Das ist im Prinzip analog zur unären Kodierung einer Zahl (siehe römisches Zahlensystem). 3.1 Rückblick: Kodierung von Zahlen Im Kodierungsfall war die Patentlösung, die Zahl zu einer bestimmten Basis zu betrachten, um den Speicherbedarf zu verringern. Das Binärsystem als Spezialfall dieser Idee, wird bekanntermaßen nativ im Rechner verwendet. Stelle Wertigkeit 8 27 7 26 6 25 5 24 4 23 3 22 2 21 1 20 Um den eigentlichen Wert der kodierten Zahl zu bestimmen, ist es in solchen Zahlensystemen notwendig, die Zahl wieder zu dekodieren. Das passiert, indem der Wert der 3 akuellen Ziffer mit der Wertigkeit der aktuellen Stelle multipliziert, und danach die Summe darüber gebildet wird. d := 101010112 = 7 X di · 2i i=0 = 1 · 20 + 1 · 21 + 1 · 23 + 1 · 25 + 1 · 27 = 17110 Offenbar lässt sich jede Zahl mit einer solchen Kodierung darstellen. 3.2 Anwendung für die Exponentiation Wir können die Potenzierungsoperation als Kodierung des Exponenten auffassen. Wenn der Trick bei der Zahlenkodierung übernommen wird, resultiert daraus für das binäre Zahlensystem der folgende Algorithmus: Algorithm 1 Schnelle Potenzierung int pow(int base, int n) { 3 int result = 1; 1 2 4 while (n != 0) { if (n & 1) result *= base; 5 6 7 8 9 base *= base; n >>= 1; 10 11 } 12 13 return result; 14 15 } Dieser Algorithmus hat eine Laufzeit von O(log(n)). 4 4 Lösungen 4.1 Sprache zu Grammatik 1. L = {abn : n ∈ N∗ } 2. L = {aa, cc, cba, bn , bn aa : n ∈ N∗ } 4.2 Grammatik zu Sprache 1. G = ({S, A, B, C}, {a, b}, P, S) mit S → aA A → aB P := B → aC C → Cb|b 2. G = ({S, A, B, C, D}, {a, b}, P, S) mit S → Ba|A A → Cb P := C → Ab|b B → Db|b D → Bb 4.3 Ist die Sprache regulär? 1. Ja. a S 2. Ja. 0,3,6,9 0,3,6,9 1,4,7 1 1,4,7 0,3,6,9 2,5,8 2,5,8 2,5,8 0 1,4,7 5 2 3. Die Sprache ist nicht regulär. Beweis. Angenommen L wäre regulär. Dann würde das Pumping-Lemma gelten, es gäbe also für jedes Wort x der Länge ≥ ` eine Zerlegung in uvw. Für jedes n ≥ 0 existiert ein Wort x = an bn in L, wobei |x| = 2n. Wenn n ≥ ` ist, befinden sich in uv nur noch a’s, da |uv| ≤ `. Da v außerdem nicht leer ist, enthält es mindestens ein a, welches nun „aufgepumpt“ werden kann. Dann enthält das resultierende Wort mehr a’s als b’s und kann deshalb nicht in L vorkommen. 4. Die Sprache ist nicht regulär. Beweis. Angenommen L wäre regulär. Dann ließe sich jede Primzahl p größer ` als Summe natürlicher Zahlen u, v und w darstellen, sodass v ≥ 1, u + v ≤ ` und für i ≥ 0 die Zahl u + iv + w ebenfalls prim wäre. Insbesondere wäre die Summe von u + (u + w) · v + w prim. ⇒ u + w + (u + w) · v = (u + w) · (v + 1) Diese Zahl ist offensichtlich zusammengesetzt, da v + 1 ≥ 2 ist. 6