Koinduktives Abzählen mit gewichteten Automaten 1 Eine Ausarbeitung im Rahmen des Seminars “Konzepte von Programmiersprachen” WS 2003/2004 von Daniel Djawadi Betreuer: Prof. Gumm, Prof. Loogen Kurzzusammenfassung: Im folgenden wird eine Methode zur Lösung einer Vielzahl von einfachen Abzählproblemen entwickelt. Die Methode besteht im wesentlichen aus drei Schritten. 1. Die zu zählenden Objekte werden in einem unendlichen gewichteten Automaten aufgezählt. 2. Dieser Automat wird mithilfe von Stream-Bisimulationen reduziert. 3. Der reduzierte Automat wird für die Berechnung eines Ausdrucks für den Stream, der alle Ergebnisse enthält, benutzt. 1 Basierend auf der Veröffentlichung “Coinductive Counting with Weighted Automata” von J.J.M.M. Rutten 1 Inhalt: 1. Ein Beispiel zur Motivation 2. Ein paar Fakten des Stream-Kalküls 3. Streams und gewichtete Automaten 4. Kompositionen von natürlichen Zahlen 5. Surjektionen 6. Wohlgeklammerte Ausdrücke 7. Literatur 2 1. Ein Beispiel zur Motivation Männliche Bienen, Drohnen genannt, haben eine Königin als Mutter aber keinen Vater. Königinnen hingegen werden durch eine Königin und eine Drohne geboren. Die ersten Stufen eines Stammbaums einer Drohne sehen demnach wie folgt aus: D K }} }} } } }} K }} }} } } }} AA AA AA AA K nn K PPPPP PPP nnn n n PPP nn n PPP n n P nnn D AA AA AA AA D D K K }} }} } } }} KA AA AA AA D Unsere Frage lautet nun: Was ist für ein k ≥ 0 die Anzahl sk der weiblichen Vorfahren der Drohne. Dabei wollen wir den Stream σ = (s0 , s1 , s2 , . . . ), der alle Antworten enthält, berechnen. Dazu gehen wir zu unendlich gewichteten Automaten über: D K OOO OOO ooo o o OOO oo o OOO o oo o OOO o w o o ' K? ? ?? ?? ?? K? ? K ?? ?? ?? K? ? D D D K K ?? ?? ?? D Hierbei stellen die Pfeile Transitionen dar, alle Königin-Zustände sind als OutputZustände gekennzeichnet. In diesem Automaten entspricht sk der Anzahl der Pfade der Länge k vom obersten Drohnen-Zustand zu einem Output-Zustand. Diese Anzahl wird von einem dem Drohnen-Zustand zugeordneten Stream repräsentiert werden, dem sogenannten Stream-Verhalten des Zustands, der mithilfe von Transitionssequenzen des Zustands definiert wird. Er repräsentiert das Transitionsverhalten eines Zustands. Mithilfe von Stream-Bisimulationen können wir nun Zustände identifizieren. Jeder Drohnen-Zustand (d.h. eigentlich der von ihm repräsentierte Stream) ist bisimular äquivalent zum Zustand q0 (also dessen Stream-Verhalten), und jeder 3 Königin-Zustand ist bisimular äquivalent zu q1 des folgenden Automaten: ) q0 i q1 w Man sieht, dass die Zustände dieses Automatens dasselbe Transitionsverhalten haben wie die zu ihnen in Relation stehenden Zustände des vorherigen Automaten, d.h. die Anzahl der Pfade der Länge k zu einem Output-Zustand sind jeweils gleich. Mit dem reduzierten Automaten berechnet man mithilfe des Stream-Kalküls einen geschlossenen Ausdruck: σ= X 1 − X − X2 (siehe Beispiel in Kapitel 3). In den folgenden zwei Kapiteln gilt es nun, die intuitiv verwendeten Schritte zu präzisieren. Danach werden drei Beispiele vorgestellt. 4 2. Ein paar Fakten des Stream-Kalküls In diesem Kapitel werden die nötigen Fakten eines koinduktiven Kalküls von Streams bereitgestellt. Definition: Die Menge aller Streams wird definiert durch Rω = { σ | σ : {0, 1, 2, . . . } → R }. Einen einzelnen Stream bezeichnen wir mit σ = (σ(0), σ(1), σ(2), . . . ) = (s0 , s1 , s2 , . . . ). Man nennt σ(0) = s0 den Initialwert von σ. Die Ableitung eines Stream ist definiert durch σ 0 = (s1 , s2 , s3 , . . . ). σ (n) bezeichnet die n-te Ableitung von σ. Sie ist definiert durch σ (0) = σ und σ (n+1) = (σ (n) )0 . Mit r bezeichnen wir den Stream (r, 0, 0, . . . ) für ein beliebiges r ∈ R. Für den koinduktiven Beweis der Gleichheit zweier Streams benötigen wir den Begriff der Stream-Bisimulation (im folgenden kurz: Bisimulation). Definition: Eine Bisimulation ist eine Relation R ⊆ Rω × Rω , so dass für alle σ, τ ∈ Rω gilt: Falls σRτ folgt σ(0) = τ (0) und σ 0 Rτ 0 . Die Vereinigung aller Bisimulationen wird mit ∼ bezeichnet. Theorem: [Koinduktion] Für alle σ, τ ∈ Rω gilt: σ ∼ τ ⇒ σ = τ Beweis: Seien σ, τ ∈ Rω und R ⊆ Rω × Rω eine Bisimulation, die das Paar (σ, τ ) enthält. Da R Bisimulation folgt per Induktion über n, dass (σ (n) , τ (n) ) ∈ R für alle n ≥ 0. Nun folgt, da R Bisimulation, dass σ (n) (0) = τ (n) (0), für alle n ≥ 0. Da σ (n) (0) = σ(n) und τ (n) (0) = τ (n) gilt also σ = τ . 2 Man kann Streams und Operationen auf Streams durch Differentialgleichungen definieren: Differentialgleichung Initialwert Name 0 0 0 (σ + τ ) = σ + τ (σ + τ )(0) = σ(0) + τ (0) Summe (σ × τ )0 = (σ 0 × τ ) + (σ(0) × τ 0 ) (σ × τ )(0) = σ(0) × τ (0) Produkt (σ −1 )0 = −σ(0)−1 × (σ 0 × σ −1 ) (σ −1 )(0) = σ(0)−1 Inverses (σ(0) 6= 0) √ √ 0 √ 0 σ √ ( σ) = σ(0) = σ(0) Quadratwurzel √ σ(0)+ σ Der Rω bildet zusammen mit den Operationen Summe, Produkt und Inverses einen kommutativen Ring. Ein Beweis für die Existenz einer eindeutigen Lösung für die obigen Differentialgleichungen findet man in [R1, Thm. 19.1]. Für viele Differentialgleichungen kann man eine geschlossene Form der Lösung berechnen, d.h. einen Ausdruck der mithilfe von Stream-Konstanten und Operatoren aufgebaut ist. Hierbei ist folgendes Theorem nützlich. 5 Fundamental Theorem: Für alle σ ∈ Rω gilt: σ = σ(0) + (X × σ 0 ). (1) Hierbei ist X definiert durch X = (0, 1, 0, 0, . . . ). Einen Beweis findet man in [R1]. Beispiel: Sei σ definiert durch: σ(0) = 1 und σ 0 = 2×σ. Mit (1) folgt nun σ = σ(0)+(X ×σ 0 ) = 1 1 + (X × 2 × σ) ⇒ (1 − (2 × X)) × σ = 1, also σ = 1−(2×X) (wobei wir einen Stream σ −1 als σ1 schreiben). Für unsere Beispiele benötigen wir eine kleine Verallgemeinerung des Begriffs der Bisimulation, so dass wir koinduktive Beweise leichter durchführen können. Definition: Eine Bisimulation-up-to ist eine Relation R ⊆ Rω × Rω , so dass für alle σ, τ ∈ Rω gilt: Falls σRτ , dann ist σ(0) = τ (0) und es existiert n ≥ 0 und Streams α0 , . . . , αn und β0 , . . . , βn , so dass σ 0 = α0 + · · · + αn und τ 0 = β0 + · · · + βn und für alle 0 ≤ 1 ≤ n ist entweder αi = βi oder αi Rβi . Wir benötigen den Begriff der Bisimulation-up-to für das Beweisprinzip der Koinduktion-up-to. Theorem: [Koinduktion-up-to] Falls σRτ für eine Bisimulation-up-to R so gilt: σ = τ. Dies zeigt man analog zum Beweis der Koinduktion. Beispiel: Seien σ, τ und ρ Streams, so dass σ(0) = τ (0) = ρ(0) = 1, σ 0 = 2 × σ und τ 0 = ρ0 = τ + ρ. Dann ist {(σ, τ ), (σ, ρ)} eine Bisimulation-up-to (man beachte σ 0 = 2 × σ = σ + σ). Per Koinduktion-up-to folgt σ = τ . 6 3. Streams und gewichtete Automaten Ein Stream kann oft durch einen gewichteten Automaten Q = (Q, ho, ti) beschrieben werden. Hierbei ist Q eine im allgemeinen unendliche Menge von Zuständen, o : Q → R die Output-Funktion und t : Q → (Q →f R) die Transitionsfunktion, wobei die Menge (Q →f R) nur Funktionen mit endlichem Träger enthält. Die Transitionsfunktion ordnet jedem Zustand q ∈ Q eine Funktion t(q) : Q →f R zu, welche ihrerseits jedem Zustand q 0 eine reelle Zahl t(q)(q 0 ) zuordnet. Diese Zahl kann man als Gewicht der Transition von q nach q 0 verstehen. Wir verwenden folgende Notation: q →r q 0 bezeichnet t(q)(q 0 ) = r, q r bezeichnet o(q) = r. Falls t(q)(q 0 ) = 1 schreiben wir einfach q → q 0 . Falls o(q) = 1, so schreiben wir q. In diesem Fall bezeichnen wir q als Output-Zustand. In Diagrammen betrachten wir nur Outputwerte, die ungleich Null sind, sowie Transitionen, deren Gewicht nicht Null ist. Wir sind nun in der Lage, einem Zustand einem Stream zuzuordnen. Definition: Das Streamverhalten S(q) ∈ Rω des Zustandes q in einem gewichteten Automaten (Q, ho, ti) kann auf zwei äquivalente Arten definiert werden: X S(q)(k) = { l1 × . . . × lk × l | ∃q0 , . . . , qk : q = q0 →l1 · · · →lk qk und o(qk ) = l } (2) Also ist S(q)(k) die gewichtete Anzahl der Pfade der Länge k von q zu einem Zustand mit einem Output der nicht Null ist. Zur Berechnung eines kompakten Ausdrucks S(q) benötigen wir folgende äquivalente Definition: Satz: Sei {q1 , . . . , qn } die Menge aller Zustände q 0 mit t(q)(q 0 ) 6= 0. Dann gilt S(q)0 = t(q)(q1 ) × S(q1 ) + · · · + t(q)(qn ) × S(qn ), S(q)(0) = o(q). Zum Beweis siehe [R1, Prop. 13.1]. Hier wird also S(q) durch ein System von Differentialgleichungen definiert, in dem S(q)0 auf die Stream-Verhalten der Folgezustände zurückgeführt wird. Nun folgt mit (1): S(q) = o(q) + (t(q)(q1 ) × X × S(q1 )) + · · · + (t(q)(qn ) × X × S(qn )) Im Fall eines endlichen Automaten ist das resultierende endliche Gleichungssystem aufgrund der Ringstruktur auf der Menge der Streams auf bekannte Weise zu lösen. Als Beispiel betrachten wir den Automat des Anfangsbeispiels. Beispiel: ) q0 i q1 w Man hat S(q0 ) = X × S(q1 ) und S(q1 ) = 1 + (X × S(q0 )) + (X × S(q1 )) ⇒ S(q0 ) = X . 1−X−X 2 7 4. Kompositionen von natürlichen Zahlen Eine Komposition einer natürlichen Zahl k ≥ 0 ist eine Sequenz von natürlichen Zahlen n1 , . . . , nl , so dass k = n1 + · · · + nl . Wir wollen wissen: Was ist für k ≥ 0 die Anzahl sk der Komposition von k? Wir berechnen σ = (s0 , s1 , . . . ) mit Hilfe der drei Schritte, die in der Einleitung erwähnt wurden. Man betrachte folgenden Ausschnitt aus einem Automaten: ε 4 UUUU 1 i i i UUUU iiii i UUUU i i i i UUUU i iii * t i 2 11 RRR o A o A RRR { AA oo o { RRR o A { o RR) { } o woo 3> 21 C 12 C 111 H HHH CC CC >> x } } x } } > C C x H# } } } ! ! ~} ~ |x 31 22 211 13 121 112 1111 In diesem Automaten entspricht z.B. der Zustand 112 der Komposition 4 = 1+1+2, der Zustand 111 der Komposition 3 = 1 + 1 + 1. Formal ist der Automat gegeben durch Q = { w | w ∈ N∗ }, o : Q → R mit o() = 0 und o(w) = 1 für alle w 6= ε und Transitionsfunktion t : Q → (Q →f R) definiert durch t(v)(w) = 1 genau dann, wenn entweder w = v · 1 gilt, oder falls v = u · k und w = u · (k + 1) für ein u ∈ Q und k ∈ N gilt. Sonst sei t(v)(w) = 0. (Man beachte, dass u · k die Konkatenation des Wortes u mit dem Buchstaben k bedeutet.) Dieser Automat zählt alle Kompositionen von natürlichen Zahlen auf (denn für eine Komposition k + 1 = n1 + · · · + nl gibt es per Induktion eine Transition von dem einzigen Zustand n1 . . . nl−1 falls nl = 1 oder von dem einzigen Zustand n1 . . . nl − 1 falls nl > 1, und damit genau einen Zustand n1 . . . nl ). Die Pfade der Länge k die in ε starten entsprechen genau den Kompositionen von k, also entspricht sk gerade der Anzahl der Pfade der Länge k die in ε beginnen. Somit folgt S(ε) = σ nach (2). Als nächstes identifizieren wir möglichst viele Zustände, indem wir eine Bisimulation-upto zwischen den Streams, die durch unseren Automaten repräsentiert werden, und denen, die der kleine Automat (siehe unten) repräsentiert, definieren. Die Indizes im folgenden Automaten zeigen, zu welchem Zustand des kleinen Automaten sie in Relation stehen. ε0 1 31 41 mm 2 mmm m m m v mm AAA A 311 221 1 V h 1 VVVV h hhh VVVV h h h h VVVV h h h h VVV* h h shhh 111 SSSS CC SSS x CC SSS ! |xxx S) 1 1 21 F 12 F 1111 I F F III v { { F F v F" F" }{{ }{{ {vv $ 2111 131 8 1211 1121 11111 q0 1 / q1 w 2 Dabei ist uns intuitiv klar, dass alle mit i induzierten Zustände und der Zustand qi dasselbe Stream-Verhalten haben, d.h. sie haben dieselbe gewichtete Anzahl der Pfade der Länge k zu einem Output-Zustand (die zwei Transitionen von einem mit 1 indizierten Zustandes spiegeln sich in einer 2-Transition des Zustandes q1 wider). Formal beweisen wir die Gleichheit S(ε) = S(q0 ) durch Koinduktion-up-to: Definiere R = {(S(ε), S(q0 ))} ∪ { (S(w), S(q1 )) | w ∈ N∗ , w 6= ε } R ist eine Bisimulation-up-to denn S(ε)(0) = 0 = S(q0 )(0) und für alle v ∈ N∗ mit v 6= ε gilt S(v)(0) = 1 = S(q1 )(0); sowie S(ε)0 = S(1) R S(q1 ) = S(q0 )0 und für alle Wörter v ∈ N∗ und natürliche Zahlen n gilt S(v · n)0 = S(v · (n + 1)) + S(v · n · 1), wobei hier jeder Summand mit S(q1 ) in Relation steht, und daher zu S(q1 )0 = 2 × S(q1 ) = S(q1 ) + S(q1 ). Da also R Bisimulation-up-to ist, folgt S(ε) = S(q0 ) per Koinduktion-up-to. Wir berechnen nun einen Ausdruck für σ = S(q0 ). Aus S(q0 ) = X × S(q1 ) und S(q1 ) = 1 + (2 × X × S(q1 )) folgt σ = S(q0 ) = 9 X . 1 − 2X 5. Surjektionen Was ist für alle k ∈ N die Anzahl sk der Surjektionen von {1, . . . , k} nach {1, 2, 3}? Hierbei sei s0 = 0 gesetzt. Wir schreiben Funktionen f als Wort f (1) . . . f (k). Der folgende Automat zählt alle so gearteten Funktionen auf. Y eeeeee ε YYYYYYYYYYY eeeeee YYYYYY e e e e e YYYY, eeee e r 1 LLL 2 LLL 3 LLL r t r t L L LLL r rrr t LL% LL% yttt % yrrr yrrr 11 u 12 KK 13 21 22 23 31 32 33 i K i i KKK ii s KKK ss u K% iiii yssss i % zuuu ysss i i ti 123 J 221 121 122 332 t 333 JJ 222 t 223 JJ 331 J t JJJ JJJ t t JJ zttt $ ztt $ $ zttt 1232 1231 1233 2231 2232 2233 3331 3332 3333 Man beachte, dass hier aus Platzgründen nicht alle Transitionen dargestellt sind. Von jedem Zustand gehen hierbei drei Transitionen aus, und die Zustände der (n + 1)-Ebene erhält man aus der n-ten Ebene durch das entsprechende Zufügen von f (n + 1). Die Zustände, die eine Surjektion repräsentieren, sind Output-Zustände. Wie im letzten Beispiel folgt S(ε) = σ = (s0 , s1 , . . . ). Nun identifizieren wir alle Zustände, die (als Wort gesehen) dieselbe Anzahl verschiedener Symbole haben, wobei unsere Idee wieder ist, dass diese Zustände dasselbe Transitions-Verhalten haben. 111 1212 eeee ε0 YYYYYYYYYY YYYYYY eeeeee e e e e e YYYYYY eeeee e YY, 1 e e e r 1 1 1 M 2 M 3 MMM M M q s M M q s MMM MMM MMM q qqq s q q q q ysss q q & & & x x 2 2 1 2 2 2 2 13 21 22 23 31 32 12 ir 331 i L L i i L L r LLL LLL ii r r tt iiii yrrr % yrrr % yttt tiiii 1222 3 1231 s y ss s 1233 K 3 1232 KKK % 2212 3 1233 2221 3 2231 ss y ss s 2232 KK 3312 22322 KKK % 22332 3322 ss y ss s 33312 3331 KK 33322 KKK % 33331 Die von den mit i indizierten Zuständen repräsentierten Streams stehen mit dem vom Zustand qi repräsentierten Stream des folgenden Automaten in Relation: 1 q0 3 / q1 2 2 / q2 3 1 / q3 Sei R = { (S(w), S(qi)) | w ∈ {1, 2, 3, }∗, i ∈ {0, 1, 2, 3} : #(w) = i } wobei #(w) die Anzahl der verschiedenen Symbole in w ist. Man rechnet leicht nach, dass R eine Bisimulation-up-to ist. Es folgt S(ε) = S(q0 ) mit Koinduktion-up-to. 10 Wir erhalten das folgende System von Differentialgleichungen: S(q0 ) S(q1 ) S(q2 ) S(q3 ) = = = = 3 × X × S(q1 ) (1 × X × S(q1 )) + (2 × X × S(q2 )) (2 × X × S(q2 )) + (1 × X × S(q3 )) 1 + (x × X × S(q3 )) Als Lösung erhält man σ = S(q0 ) = 3!X 3 . (1 − X)(1 − 2X)(1 − 3X) 11 6. Wohlgeklammerte Ausdrücke In den letzten Beispielen hatten wir das Glück“, dass die Zustände der Automaten ” jeweils endlich viel verschiedene Stream-Verhalten hatten. Als Resultat des Identifikationsschrittes erhielten wir somit endliche Automaten, was zu endlichen Gleichungssystemen führte. In diesem Beispiel ist dies nicht der Fall. Man betrachte das Alphabet {(, )}. Was ist für alle k ≥ 0 die Anzahl sk der wohlgeklammerten Ausdrücke der Länge k über diesem Alphabet? Die Output-Zustände des folgenden Automaten entsprechen genau diesen Ausdrücken. ε (Q | QQQ QQQ QQQ QQQ QQQ QQQ ( || || | || }| | () ()( ()() || || | || }| | (() | || || | }| | (()) ()(( | || || | }| | (()( (( B BB BB BB BB ! ((() ((( || || | | }| | (((( Wieder gilt S(ε) = σ = (s0 , s1 , . . . ). Wir identifizieren Zustände nach der Anzahl der Linksklammern ohne passende Rechtsklammer. ε0 ()0 ()( ()()0 zz zz z z zz |z z (1 RRRR RRR RRR RRR RRR RRR R( 1 (() zz zz z z |z z (())0 ()((2 zz zz z zz |z z 1 zz zz z z |z z (()(2 ((()2 Dies führt nun zu einem unendlichen Automaten: q0 i 1 1 ) 1 q1 i 1 12 ) 1 q2 i 1 ((2 D DD DD DD D ). . . D" (((3 zz zz z zz |z z ((((4 Wieder folgt per Koinduktion-up-to: S(q0 ) = S(ε). S(q0 ) ist gegeben als die eindeutige Lösung des Systems S(q0 ) = 1 + (X × S(q1 )) und S(qi ) = (X × S(qi−1 )) + (X × S(qi+1 )) für alle i ≥ 1 Statt zu versuchen das System zu lösen, nutzen wir ein Resultat auf Automaten. Man betrachte den Automat l0 l1 u0 q0 i d1 ) l2 u1 q1 i ) u2 q2 i d2 ). . . d3 Es gilt: Theorem: Das Stream-Verhalten S(q0 ) in den Automaten oben ist gegeben durch den folgenden Kettenbruch: S(q0 ) = 1 (u0 × X) × (d1 × X) 1 − (l0 × X) − (u1 × x) × (d2 × X) 1 − (l1 × X) − (u2 × X) × (d3 × X) 1 − (l2 × X) − ... Beweisskizze: Seien σ0 , σ1 , . . . eindeutige Lösungen von σi0 = (li × σi ) + (ui × σi+1 × di × X × σi ), σi (0) = 1 Aus (1) folgt σi = 1 1 − (li × X) − (ui × X) × σi+1 × (di+1 × X) Der Kettenbruch ist nun als suggestive Notation für σ0 zu verstehen. Man beweist S(q0 ) = σ0 per Koinduktion-up-to. 2 Die Anwendung des Theorems auf unseren reduzierten unendlichen Automaten führt zu σ = S(q0 ) = 1 1− X2 2 1− X ... , wobei nach der Beweisskizze σ gegeben ist durch σ = 2 von (X 2 × σ 2 ) − σ + 1 = 0 ⇒ σ = 1+√1−4×X 2. 13 1 . 1−(X×σ×X) Also ist σ Lösung 7. Literatur Weitere Informationen zum Stream-Kalkül finden sich in: [R1 ] J.J.M.M. Rutten: Elements of stream calculus; in: Stephen Brooks and Michael Mislove, eds., Proceedings of MFPS 2001: Seventeenth Conference on the Mathematical Foundations of Programming Semantics, vol. 45 of Electronic Notes in Theoretical Computer Sci., pages 1-66. Elsevier Science Publishers, 2001. Mehr zu Kettenbrüchen in der Kombinatorik findet man in: P. Flajolet: Combinatorial aspects of continued fractions. Discrete Mathematics, 32, pages 125-161, 1980. Desweiteren sei auf die ausführliche Originalarbeit verwiesen. 14