-
Notifications
You must be signed in to change notification settings - Fork 0
/
swp_2.tex
2099 lines (1906 loc) · 124 KB
/
swp_2.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Semantik von Programmiersprachen}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
Im ersten Kapitel haben wir uns damit beschäftigt wie ein Wort (Programm) einer Sprache eindeutig geparst werden kann.
Die Wörter (Programme) haben jedoch noch keine Bedeutung. Wir wollen uns nun damit beschäftigen
Sprachen eine Bedeutung zu geben und Sprachen anhand der Bedeutung der Wörter
zu unterscheiden. Im Kontext der Semantik verwenden wir vermehrt den Begriff ``Programm einer Programmiersprache'' anstatt ``Wort einer Sprache''.
Im zweiten Kapitel betrachten wir nur noch syntaktisch korrekte Eingaben, d.h. wir betrachten den Fall nachdem der Parser bereits
entschieden hat, dass eine Eingabe ein syntaktisch gültiges Programm ist.
Wir teilen dazu Sprachen hauptsächlich in funktionale, imperative und logische Sprachen.
Zu jedem dieser drei Sprachparadigmen werden wir Sprachen konstruieren und deren
Semantik definieren.
Sowohl für die Definition der Semantik als auch für die Interpretation eines konkreten Programms
in einer Sprache, werden wir mathematische Funktionen definieren: die Interpretationsfunktion sowie weitere Hilfsfunktionen.
Diese mathematische Definition wird es uns erlauben die Korrektheit unserer Programme
zu beweisen.
Um Syntax und Semantik zu unterscheiden werden wir Programme einer Sprache wie bisher unterstreichen.
Die Beschreibung der Semantik ist kein Programm und wird daher auch keinesfalls unterstrichen.
\begin{bsp}
Was drückt der Ausdruck \u{a = b + c} aus? (vgl. Vorlesungsskriptum Seite 42)
Es gibt einige mögliche Interpretationen, hier eine Auswahl davon:
\begin{\whichenum}
\item Imperative Interpretation: Eine Zuweisung wie in $C$. \u{a} hat nach der Ausführung des Ausdrucks den Wert der Summe der Werte von \u{b} und \u{c}.
Andere Variante: Der Wert von \u{a} ist nach der Zuweisung die Zeichenfolge \u{b + c}.
\item Funktionale Interpretation: Eine Funktion \u{a} wird mit den 4 Parametern \u{= b + c} aufgerufen.
\item Logische Interpretation: Ein logischer Ausdruck, beispielsweise ist der Ausdruck Wahr wenn der Wert von \u{a} gleich der Summe der Werte von \u{b} und \u{c} ist.
Andere Variante: Der Wert von 2 der 3 Variablen ist bekannt, der Wert der 3. Variable wird so festgelegt.
\end{\whichenum}
Wir sehen anhand dieses Beispiels, dass es wichtig ist exakt zu definieren wie ein Ausdruck
zu interpretieren ist.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
In funktionalen Programmiersprachen besteht jedes Programm aus einer oder mehreren
Funktionen.
\begin{defn}[Funktion]\label{defn:Funktion}
Eine Funktion ist eine Relation zwischen einer Menge $A$ und einer Menge $B$.
Jedem Element aus der Menge $A$ wird genau ein Element der Menge $B$ zugeordnet.
Das heißt: Für jeden möglichen Eingabewert gibt es genau einen Ausgabewert.
\end{defn}
\section{Sprache $\lng{A}$ - einfache arithmetische Ausdrücke}
Arithmetische Ausdrücke sind Funktionen. Wir können beispielsweise die Funktionen
Addition, Subtraktion und Multiplikation von zwei Zahlen in $\R$ definieren mit einem
Eingabewert in $\R \times \R$ und einen Ausgabewert in $\R$. Auch die Division
können wir als Funktion definieren von $\R \times \R \setminus \gbr{0}$ (Division durch $0$ schließen
wir damit aus, da die Division in diesem Fall nicht als Funktion definiert ist) auf Ausgabewerte in $\R$.
\begin{defn}
Die Sprache $\lng{A}$ definieren wir mit Alphabet $\Sigma=\gbr{\u{0},\ldots,\u{9},\u{(},\u{)},\u{+}}$.
Zwecks Einfachheit definieren wir Ziffern (D, digits) und Zahlen:
\begin{\whichitem}
\item $\lng{A}_D = \gbr{\u{0},\ldots,\u{9}}$
\item ZAHL $= (\lng{A}_D \setminus \gbr{\u{0}} \lng{A}_D^*) \cup \gbr{\u{0}}$
\end{\whichitem}
Wir definieren die Sprache $A$ nun nicht mehr über eine Grammatik sondern durch eine induktive Beschreibung (Basisfall und allgemeine Fälle):
\begin{\whichenum}
\item ZAHL$\subset \lng{A}$
\item Wenn $x,y \in \lng{A}$, dann ist auch $\u{(} x \u{)} \u{+} \u{(} y \u{)} \in \lng{A}$.
\end{\whichenum}
\end{defn}
An dieser Stelle sei noch einmal darauf hingewiesen, dass wir $x,y$ nicht unterstreichen dürfen, da sie keine Sprachelemente sind sondern
Platzhalter, mathematisch würde man sie auch als Variablen bezeichnen.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
Wir wollen nun mit unserer Sprache $\lng{A}$ Ausdrücke berechnen können.
Dazu definieren wir eines unserer mächtigsten Werkzeuge im zweiten Kapitel:
Die Interpretationsfunktion $I$ (auch genannt Semantikfunktion).
Man kann sich diese Funktion vorstellen wie einen Interpreter einer Scriptsprache:
Wir geben ein Programm ein und führen es aus, abhängig vom aktuellen Zustand liefert
uns der Interpreter ein Ergebnis zurück.
Genau so soll unsere Interpretationsfunktion arbeiten.
Wir erwarten einen Eingabewert aus $\lng{A}$ und bilden auf $\N_0$ ab, d.h. geben
einen Wert aus $\N_0$ zurück.
Genau wie die Syntax werden wir nun die Semantik induktiv durch die Interpretationsfunktion definieren.
\ifthenelse{\boolean{long}}{}{\end{comment}}
\begin{defn}
Die Semantik der Sprache $\lng{A}$ definieren wir durch:
\begin{\whichenum}
\item $I_{\lng{A}}(x) = \sbr{x}$ wenn $x \in \lng{A}_N$. $x$ ist dabei eine Zeichenkette im Programm, $\sbr{x}$ die
entsprechende Repräsentation in $\N_0$.
\item $I_{\lng{A}}(\u{(}x\u{)+(}y\u{)})=I_{\lng{A}}(x) + I_{\lng{A}}(y)$ wenn $x,y \in \lng{A}$.
\end{\whichenum}
\end{defn}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Das Programm $\u{((10)+(9))+(3)}$ (vgl. Vorlesungsskriptum S.45) können wir wie folgt interpretieren:
\begin{align*}
I_{\lng{A}}(\u{((10)+(9))+(3)}) &= I_{\lng{A}}(\u{(10)+(9)}) + I_{\lng{A}}(\u{3}) \tag{entsprechend 2. Fall der Definition} \\
&= I_{\lng{A}}(\u{10}) + I_{\lng{A}}(\u{9}) + 3 \tag{beim $\u{3}$ nun der 1. Fall der Definition} \\
&= 10 + 9 + 3 = 22
\end{align*}
\end{bsp}
Auch hier sehen wir wieder deutlich die Unterscheidung zwischen Zeichenketten im Programmcode (unterstrichen) und den Werten
auf der semantischen Ebene (nicht unterstrichen). Um den Unterschied weiter zu verdeutlichen
definieren wir nun die Sprache der einfachen arithmetischen Ausdrücke von Binärzahlen $\lng{B}$.
Die Sprache $\lng{B}$ definieren wir mit Alphabet $\Sigma=\gbr{\u{0},\u{1},\u{(},\u{)},\u{+}}$.
\begin{\whichenum}
\item $(\u{1} \gbr{\u{0},\u{1}}^*) \cup \gbr{\u{0}} \subset \lng{B}$
\item Wenn $x,y \in \lng{B}$, dann ist auch $\u{(} x \u{)} \u{+} \u{(} y \u{)} \in \lng{B}$.
\end{\whichenum}
Die Semantik der Sprache $\lng{B}$ definieren wir durch:
\begin{\whichenum}
\item $I_{\lng{B}}(x) = \sbr{x}$ wenn $x \in \lng{B}_N$. $\sbr{x} \in \N_0$ ist nun die
durch die Binärzahl (exakt: die Binärziffernfolge) dargestellte Zahl auf semantischer Ebene, in diesem Fall also im mathematischen Sinne.
\item $I(\u{(}x\u{)+(}y\u{)})=I(x) + I(y)$ wenn $x,y \in \lng{B}$.
\end{\whichenum}
\begin{bsp}
$I(\u{1001})=9$ aber $\u{1001}\neq 9$.
Betrachten wir das Beispiel wie zuvor, nun in Binärdarstellung $\u{((1010)+(1001))+(11)}$:
\begin{align*}
I_{\lng{B}}(\u{((1010)+(1001))+(11)}) &= I_{\lng{B}}(\u{(1010)+(1001)}) + I_{\lng{B}}(\u{11})\\
&= I_{\lng{B}}(\u{1010}) + I_{\lng{B}}(\u{1001}) + 3\\
&= 10 + 9 + 3 = 22
\end{align*}
\end{bsp}
Wir versuchen nun der Sprache $\lng{A}$ eine zweite Funktion, die Multiplikation hinzuzufügen.
Die Sprache $\lng{D}$ ist definiert durch:
\begin{\whichenum}
\item ZAHL$\subset \lng{D}$
\item $\u{(} x \u{)} \u{+} \u{(} y \u{)} \in \lng{D}$, wenn $x,y \in \lng{D}$.
\item $\u{(} x \u{)} \u{*} \u{(} y \u{)} \in \lng{D}$, wenn $x,y \in \lng{D}$.
\end{\whichenum}
Die Semantik der Sprache $\lng{D}$ definieren wir durch:
\begin{\whichenum}
\item $I_{\lng{D}}(x) = \sbr{x}$ wenn $x \in \lng{D}_N$.
\item $I_{\lng{D}}(\u{(}x\u{)+(}y\u{)})=I_{\lng{D}}(x) + I_{\lng{D}}(y)$ wenn $x,y \in \lng{A}$.
\item $I_{\lng{D}}(\u{(}x\u{)*(}y\u{)})=I_{\lng{D}}(x) \cdot I_{\lng{D}}(y)$ wenn $x,y \in \lng{A}$.
\end{\whichenum}
Würden wir die Klammern aus der Definition $I_{\lng{D}}$ weglassen, so würde es sich nicht um eine Funktion handeln.
Wir nennen diese Sprache ohne Klammern $I_{\lng{D}'}$ um anhand dieser Beweise über die Interpretationsfunktion zu üben.
\begin{beweis}
Laut Definition~\ref{defn:Funktion} ist eine Relation eine Funktion wenn es für jeden möglichen Eingabewert genau einen Ausgabewert gibt.
Möchte man eine Aussage über ``alle'' Werte bzw. ``jeden'' Wert widerlegen so gestaltet sich ein Beweis oft relativ einfach. In so einem
Fall müssen wir nur ein Gegenbeispiel finden, denn dann gilt die Aussage offensichtlich nicht für alle Werte, wir haben ja einen gefunden
für den es nicht gilt. Diese Beweistechnik nennt man ``Beweis durch Widerspruch''.
Wir werden nun zeigen, dass $I_{\lng{D}'}$ für das Programm \u{1+2*3} verschiedene Interpretationsmöglichkeiten zulässt da nicht festgelegt
ist ob der 2. oder 3. Fall der Definition die höhere Priorität hat.
\begin{align*}
I_{\lng{D}'}(\u{1+2*3}) &= I_{\lng{D}'}(\u{1+2}) \cdot I_{\lng{D}'}(\u{3}) \tag{3. Fall der Definition} \\
&= (I_{\lng{D}'}(\u{1}) + I_{\lng{D}'}(\u{2})) \cdot 3 \tag{2. Fall der Definition} \\
&= (1+2) \cdot 3 = 3 \cdot 3 = 9 \\
I_{\lng{D}'}(\u{1+2*3}) &= I_{\lng{D}'}(\u{1}) + I_{\lng{D}'}(\u{2*3}) \tag{2. Fall der Definition} \\
&= 1 + (I_{\lng{D}'}(\u{2}) \cdot I_{\lng{D}'}(\u{3})) \tag{3. Fall der Definition} \\
&= 1 + (2 \cdot 3) = 1 + 6 = 7 \neq 9
\end{align*}
Wir haben gezeigt, dass für einen Eingabewert mehrere unterschiedliche Ausgabewerte möglich sind.
Folglich gibt es nicht für \u{jeden} Eingabewert \u{genau einen} Ausgabewert, daher kann $I_{\lng{D}'}$ keine Funktion sein. \hfill $\Box$
\end{beweis}
Syntax und Semantik müssen also eindeutig sein, damit die Interpretationsfunktion eine Funktion ist.
\ifthenelse{\boolean{long}}{}{\end{comment}}
\section{Sprache $\lng{V}$ - arithmetische Ausdrücke mit Variablen}
Wir erweitern die Sprache $\lng{A}$ durch Variablen und schaffen so eine mächtigere Sprache $\lng{V}$.
Um mit Variablen umgehen zu können brauchen wir nun einerseits eine Menge zulässiger
Variablennamen und andererseits eine Funktion die von Variablennamen auf eine Wertemenge der semantischen Ebene (z.B. $\N_0$) abbildet.
Die Menge der zulässigen Variablennamen nennen wir IVS (Individuenvariablensymbole).
\begin{defn}
Zwecks Einfachheit erlauben wir nur wenige Variablennamen und definieren daher
\[\text{IVS} = \gbr{\u{a},\u{b},\ldots,\u{z}} \cup \gbr{\u{x1},\u{x2},\ldots}.\]
\end{defn}
Die Funktion die von Variablennamen auf eine Wertemenge abbildet nennen wir $\omega$-Environment, (Variablen-)Umgebung.
Man kann sich diese Funktion auch als Tabelle vorstellen bzw. in einem Interpreter als Tabelle implementieren.
\begin{defn}
Die Menge aller Environments sei
\[\text{ENV} = \gbr{x | x \in \P\rbr{\text{IVS} \times \Lambda}}, \forall \rbr{a,b},\rbr{a',b'} \in x : \quad a = a' \to b = b',\]
das heißt, die Potenzmenge des kartesischen Produkts der Variablennamen und der Werte, wobei es keine Tupel gibt, bei denen der gleiche Variablenname mit unterschiedlichen Werten verknüpft ist.
\end{defn}
$\text{IVS} \times \Lambda$ wäre hierbei die Menge die alle möglichen Variablennamen mit allen möglichen Werten verknüpft. Die Potenzmenge dieser Menge enthält alle Teilmengen, das heißt auch jedes spezielle Environment (und ungültige) ist in dieser Menge enthalten. Mit der zusätzlichen Bedingung am Ende der Definition wird die Einschränkung auf gültige Environments getroffen.
Für die Sprache $\lng{V}$ ist $\Lambda=\N_0$.
\begin{defn}
Die Syntax der Sprache $\lng{V}$ ist definiert durch:
\begin{\whichenum}
\item ZAHL$\subset \lng{V}$
\item IVS$\subset \lng{V}$
\item $\u{(} x \u{)} \u{+} \u{(} y \u{)} \in \lng{V}$, wenn $x,y \in \lng{V}$.
\end{\whichenum}
\end{defn}
Die Interpretation eines Programms hängt nun nicht mehr allein vom Programm selbst ab,
sondern auch von den Werten der Variablen im $\omega$-Environment.
\begin{defn}
Die Interpretationsfunktion $I_{\lng{V}}: \text{ENV}\times\lng{V} \to \Lambda$
weist jedem Tupel aus Environment und Programm einen Wert in $\Lambda$ zu.
\begin{\whichenum}
\item $I_{\lng{V}}(\omega,k) = \sbr{k}$ wenn $k \in \text{ZAHL}$, $\omega \in \text{ENV}$.
\item $I_{\lng{V}}(\omega,v) = \omega(v)$ wenn $v \in \text{IVS}$, $\omega \in \text{ENV}$.
\item $I_{\lng{V}}(\u{(}x\u{)+(}y\u{)})=I_{\lng{V}}(\omega,x) + I_{\lng{V}}(\omega,y)$ wenn $x,y \in \lng{V}$, $\omega \in \text{ENV}$.
\end{\whichenum}
\end{defn}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Gegeben sei das Environment $\omega(\u{x})=0$, $\omega(\u{y})=1$, $\omega(\u{z})=2$.
Interpretieren Sie das Programm $\u{(((x)+(2))+(y))+(z)}$.
\begin{align*}
I_{\lng{V}}(\omega,\u{(((x)+(2))+(y))+(z)}) &= I_{\lng{V}}(\omega,\u{((x)+(2))+(y)}) + I_{\lng{V}}(\omega,\u{z}) \\
&= I_{\lng{V}}(\omega,\u{(x)+(2)}) + I_{\lng{V}}(\omega,\u{y}) + \omega(\u{z}) \\
&= I_{\lng{V}}(\omega,\u{x}) + I_{\lng{V}}(\omega,\u{2}) + \omega(\u{y}) + 2 \\
&= \omega(\u{x}) + 2 + 1 + 2 \\
&= 0 + 2 + 1 + 2 = 5
\end{align*}
Beachten Sie auch, dass nach wie vor $I_{\lng{V}}(\omega,\u{2})=2$.
Es ist ein bei den Übungen weit verbreiteter Fehler $I_{\lng{V}}(\omega,\u{2}) = \omega(\u{2})$ zu schreiben. Die Interpretationsfunktion wurde so nicht definiert und
außerdem ist $\u{2}$ auch kein gültiger Variablenname.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\section{Datentypen}
Bisher haben wir eine Sprache nur für einen Datentypen definiert. Dieser war implizit in der
Definition der Sprache drin (beispielsweise die natürlichen Zahlen). Derartige Definitionen
erlauben kein Ersetzen des Datentyps ohne die Definition der Sprache wesentlich zu überarbeiten.
Da wir dies aber häufig wollen werden wir nun zuerst Datentypen auf der semantischen Ebene
und anschließend die Repräsentation von Datentypen auf der syntaktischen Ebene definieren.
\begin{defn}[Datentyp]
Ein Datentyp ist ein Tupel $\Psi=\rbr{A,F,P,C}$ mit
\begin{\whichitem}
\item $A$: Grundmenge (Wertebereich)
\item $F$: Menge von Funktionen $f_i: A^{k_i} \to A^{l_i}$.
$f_i$ ist die $i$-te Funktion in der Menge, $k_i$ die Dimension vom Urbild (Dimension des Inputs, Anzahl der Funktionsargumente) und $l_i$
die Dimension vom Bild der $i$-ten Funktion (Dimension des Outputs, Anzahl der Funktionsrückgabewerte).
\item $P$: Menge von Prädikaten $p_i: A^{k_i} \to \gbr{T,F}$.
$p_i$ ist die $i$-te Funktion in der Menge und $k_i$ die Dimension vom Urbild (Dimension des Inputs, Anzahl der Funktionsargumente) der $i$-ten Funktion.
\item $C$: Menge von Konstanten $c_i$ wobei $c \subseteq A$.
\end{\whichitem}
Die Mengen $F^{\Sigma}$, $P^{\Sigma}$ und $C^{\Sigma}$ enthalten die entsprechenden Symbole für die syntaktische Repräsentation:
\begin{\whichitem}
\item Funktionssymbole $F^{\Sigma}$: je ein Symbol $f^{\Sigma}_i$ (z.B. Name der Funktion) für jede Funktion $f_i$
\item Prädikatensymbole $P^{\Sigma}$: je ein Symbol $p^{\Sigma}_i$ (z.B. Name des Prädikats) für jedes Prädikat $p_i$
\item Konstantensymbol $C^{\Sigma}$: je ein Symbol $c^{\Sigma}_i$ (z.B. ausgeschriebene Form der Konstante) für jede Konstante $c_i$
\end{\whichitem}
\end{defn}
Konstanten sind eigentlich nur spezielle Funktionen ($0$ Argumente) und wir unterscheiden nur zwecks Übersicht.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Definieren Sie den Datentyp Integer mit Funktionen für Addition, Subtraktion und Multiplikation sowie Prädikaten für
``kleiner'' und Gleichheit.
\textit{Lösung:}
Im Fall der Integer ist die Definition der Funktionen und Prädikate trivial, da
alle Funktionen und Prädikate durch die entsprechenden Operationen auf den ganzen Zahlen $\Z$ definiert sind.
Daher genügt es zu definieren welche Funktion welcher Operation entspricht.
\begin{\whichitem}\label{defn:integer}
\item Grundmenge $A=\Z$
\item Funktionen $f_1: +$, $f_2: -$, $f_3: *$
Die Funktionen $+, -, *$ sind auf $\Z$ definiert.
Auf der syntaktischen Ebene definieren wir: $f^{\Sigma}_1: {\tuplus}$, $f^{\Sigma}_2: {\tuminus}$, $f^{\Sigma}_3: {\tumult}$.
\item Prädikate $p_1: <$, $p_2: =$
Die Prädikate $<, =$ sind auf $\Z$ definiert.
Syntaktische Ebene: $p^{\Sigma}_1: {\tult}$, $p^{\Sigma}_2: {\tueq}$.
\item Konstanten $c_1: 0$, $c_2: 1$
Syntaktische Ebene: $c^{\Sigma}_1: {\tunull}$, $c^{\Sigma}_2: {\tueins}$.
\end{\whichitem}
Hinzunahme von Division ist problematisch $/$ da das Ergebnis nicht unbedingt $\in A$ ist.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
Wir können bei der Definition eines Datentyps oft (z.B. bei den verschiedenen Datentypen für Zahlen) auf bekannte algebraische Strukturen (Halbgruppen, etc.) zurückgreifen.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Definieren Sie den Datentyp String mit der Funktion Konkatenation und dem Prädikat ``Präfix''.
\textit{Lösung:} Hier können wir nun nicht mehr auf eine vorhandene mathematische Definition
zurückgreifen.
\begin{\whichitem}
\item Grundmenge $A=V^*$ mit $V$ einem endlichen Alphabet $\gbr{v_1,\ldots,v_n}$ (z.B. dem ASCII-Alphabet).
\item Funktionen
\begin{\whichenum}
\item $f_1: \circ$ (Konkatenation)
\begin{\whichitem}
\item Wenn $x \in V^*$ ist, dann ist $x \circ \varepsilon = x$
\item Wenn $x \in V^*$ und $a \in V$ ist, dann ist $x \circ a = xa$
\item Wenn $x,y \in V^*$ und $a \in V$ ist, dann ist $x \circ (y \circ a) = (x \circ y) \circ a$
\end{\whichitem}
\end{\whichenum}
\item Prädikate
\begin{\whichenum}
\item $p_1: <<$ (Präfix)
\begin{\whichitem}
\item Wenn $x \in V^*$ ist, dann ist $\varepsilon << x$
\item Wenn $x \in V^*$ ist, dann ist $x << x$
\item Wenn $x$ Präfix von $y$ ist, dann ist $x$ auch Präfix von $y \circ z$
($(x << y) \ra (x << (y \circ z))$).
\end{\whichitem}
\end{\whichenum}
\item Konstanten $c_i: v_i$, $c_{n+1}: \varepsilon$ (eine Konstante für jeden Buchstaben des Alphabets und $\varepsilon$ für den Leerstring).
\end{\whichitem}
Die syntaktische Ebene überlassen wir dem Leser.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Definieren Sie den Datentyp des binären Stacks mit Funktionen um Elemente auf den Stack zu legen oder herunterzunehmen, sowie
Prädikaten zur Überprüfung des obersten Elementes.
\textit{Lösung:}
\begin{\whichitem}
\item Grundmenge $A=\gbr{0,1}^* \cup \gbr{\varepsilon}$, d.h. Ziffernfolgen aus $0$ und $1$ oder $\varepsilon$ (leerer Stack).
\item Funktionen
\begin{\whichenum}
\item $f_1: \text{add0}$ liefert den Stack mit einer $0$ daraufgelegt.
\begin{\whichitem}
\item $\text{add0}(\varepsilon)=0$
\item $\text{add0}(x)=0x$ (mit $x \neq \varepsilon$)
\end{\whichitem}
\item $f_2: \text{add1}$ liefert den Stack mit einer $1$ daraufgelegt.
\begin{\whichitem}
\item $\text{add1}(\varepsilon)=1$
\item $\text{add1}(x)=1x$ (mit $x \neq \varepsilon$)
\end{\whichitem}
\item $f_3: \text{sub}$ liefert den Stack ohne das oberste Element.
\begin{\whichitem}
\item $\text{sub}(\varepsilon)=\varepsilon$
\item $\text{sub}(ax)=x$ (mit $a \neq \varepsilon$)
\end{\whichitem}
\end{\whichenum}
\item Prädikate
\begin{\whichenum}
\item $p_1: \text{ist0?}$ testet ob das oberste Element $0$ ist.
\begin{\whichitem}
\item $\text{ist0?}(x) \Lra \texists z : x = 0z$
\end{\whichitem}
\item $p_2: \text{ist1?}$ testet ob das oberste Element $1$ ist.
\begin{\whichitem}
\item $\text{ist1?}(x) \Lra \texists z : x = 1z$
\end{\whichitem}
\item $p_3: \text{istLeer?}$ testet ob das oberste Element $\varepsilon$ ist.
\begin{\whichitem}
\item $\text{istLeer?}(x) \Lra x = \varepsilon$
\end{\whichitem}
\end{\whichenum}
\item Konstanten $c_1: \varepsilon$.
\end{\whichitem}
Auf der syntaktischen Ebene werden die gleichen Bezeichnungen wie auf der semantischen Ebene verwendet.
\end{bsp}
\begin{bsp}
Berechnen Sie den Ausdruck $\text{add0}(\text{add1}(\text{sub}(011)))$ im Datentyp des binären Stacks.
\textit{Lösung:}
\[\text{add0}(\text{add1}(\text{sub}(011))) = \text{add0}(\text{add1}(11)) = \text{add0}(111) = 0111\]
\begin{align*}
\text{ist0?}(0111)&=T \\
\text{ist1?}(0111)&=F \\
\text{istLeer?}(0111)&=F
\end{align*}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\section{Sprache der Terme $\lng{T}$}
Wir müssen nun um den Datentyp verwenden zu können eine grundlegende Sprache
definieren die diesen Datentyp verwendet. Auf dieser Sprache können dann weitere Sprachen
aufgebaut werden.
\begin{defn}[Sprache der Terme $\lng{T}$]\label{defn:semt}
Sei $\Psi=\rbr{A,F,P,C}$ ein Datentyp.
Das Alphabet $\Sigma$ ist dann eine Vereinigung aus den Mengen der
\begin{\whichitem}
\item IVS (Individuenvariablensymbole)
\item Funktionssymbole $F^{\Sigma}$
\item Prädikatensymbole $P^{\Sigma}$
\item Konstantensymbol $C^{\Sigma}$
\item $\u{(}$,$\u{)}$ und $\u{,}$
\item Sondersymbole (Keywords): \u{if}, \u{then}, \u{else}, \u{begin}, \u{end}, $\ldots$
\end{\whichitem}
Die Syntax von $\lng{T} \subseteq \Sigma$ über einem beliebigen Datentypen ist dann definiert durch:
\begin{\whichenum}
\item $C^{\Sigma} \subseteq \lng{T}$, d.h. Konstantensymbole sind Terme
\item $\text{IVS} \subseteq \lng{T}$, d.h. Individuenvariablensymbole sind Terme
\item Wenn $f^{\Sigma}_i$ ein $n$-stelliges Funktionssymbol ist und $t_1,\ldots,t_n$ Terme,
dann ist auch $f^{\Sigma}_i\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}$ ein Term (Unterstreichungen beachten!).
\end{\whichenum}
Die Semantik von $\lng{T}$ definieren wir durch die Interpretationsfunktion $I_{\lng{T}}: \text{ENV} \times \lng{T} \to A$.
\begin{\whichenum}
\item $I_{\lng{T}}(\omega,c^{\Sigma}_i)=c_i$ mit $c_i \in C$ (Semantik-Ebene), $c^{\Sigma}_i \in C^{\Sigma}$ (Syntax-Ebene) und $\omega \in \text{ENV}$.
\item $I_{\lng{T}}(\omega,v)=\omega(v)$ mit $v \in \text{IVS}$ und $\omega \in \text{ENV}$.
\item $I_{\lng{T}}(\omega,f^{\Sigma}_i\u{(}t_1\u{,}\ldots\u{,}t_n\u{)})=f_i(I_{\lng{T}}(\omega,t_1),\ldots,I_{\lng{T}}(\omega,t_n))$ mit $f_i \in F$ (Semantik-Ebene), $f^{\Sigma}_i \in F^{\Sigma}$ (Syntax-Ebene) und $\omega \in \text{ENV}$.
\end{\whichenum}
\end{defn}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Führen Sie das Programm \u{plus(plus(x,y),plus(eins,z))} mit dem Environment $\omega(\u{x})=0$, $\omega(\u{y})=1$, $\omega(\u{z})=2$ aus.
\textit{Lösung:}
\begin{align*}
&\quad \I{T}{\omega}{plus(plus(x,y),plus(eins,z))}\\
&= \I{T}{\omega}{plus(x,y)} + \I{T}{\omega}{plus(eins,z)} \\
&= \rbr{\I{T}{\omega}{x} + \I{T}{\omega}{y}} + \rbr{\I{T}{\omega}{eins} + \I{T}{\omega}{z}} \\
&= \omega(\u{x}) + \omega(\u{y}) + 1 + \omega(\u{z}) \\
&= 0+1+1+2 = 4
\end{align*}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
Laut Definition von $\lng{T}$ gibt es nur die Konstanten $0$ und $1$. Variablen können natürlich jeden beliebigen Wert in $\Z$ annehmen.
Es kann aber auch gezeigt werden, dass alle ganzen Zahlen durch einen variablenfreien Term dargestellt werden können. Daher ist es nicht nötig, dass es für jede Zahl eine Konstante gibt.
Terme sind rekursiv definiert. Die \textbf{vollständige Induktion} (ab hier auch Induktion genannt) ist die übliche Beweistechnik für Beweise über rekursive bzw. rekursiv definierte Ausdrücke.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
Versuchen wir zunächst die \textbf{vollständige Induktion} ganz allgemein zu verstehen.
\begin{bsp}
Dazu macht es Sinn sich ein kleines Beispiel zu überlegen. Dazu definieren wir, dass folgende Aussagen wahr sind:
\begin{\whichitem}
\item Aussage $A$: An Tag $n$ regnet es genau dann, wenn es an Tag $n-1$ geregnet hat.
\item Aussage $T_1$: An Tag $1$ regnet es.
\end{\whichitem}
Wir sehen sofort, dass es wohl immer regnet.
Dies wollen wir nun auch beweisen: An jedem Tag regnet es. Man könnte auch schreiben:
An jedem Tag $i$ regnet es. Zwecks Übersichtlichkeit bezeichnen wir die Aussage ``Es regnet an Tag $i$'' mit $T_i$
und können dann sehr kompakt schreiben: $\tforall i: T_i$.
Wir erbringen nun zunächst den Beweis für die ersten Tage einzeln.
\begin{\whichitem}
\item Tag $1$: $T_1$ war schon gegeben und ist wahr.
\item Tag $2$: $A \wedge T_1 \ra T_2$
\item Tag $3$: $A \wedge T_1 \wedge T_2 \ra T_3$
\item Tag $4$: $A \wedge T_1 \wedge T_2 \wedge T_3 \ra T_4$
\end{\whichitem}
Wir würden so allerdings nie fertig werden da es in unserem Beispiel so viele Tage wie natürliche Zahlen gibt.
Was uns aber auffällt: Für den Beweis von jedem $T_i$ müssen wir auf den Beweis für $T_{i-1}$ zurückgreifen.
Eine Induktion verkürzt hier unsere Arbeit wesentlich.
Wir zeigen einfach die Korrektheit für einen allgemeinen Fall (z.B. $T_{n+1}$) aus seinen Vorgängern ($T_{i}$ mit $i \leq n$) folgt.
Dazu müssen wir zunächst allgemein beschreiben was für jedes einzelne Element bis zu einem gewissen (beliebigen) $n$ gilt: $\tforall i \leq n: T_i$. Wir nennen dies \textbf{Induktionshypothese}.
Diese Aussage ist allerdings nicht bewiesen, es ist lediglich eine Annahme darüber was für jedes Element gilt.
Den entscheidenden Schritt im Beweis führen wir jetzt durch, indem wir von $n$ auf das nachfolgende Element (in unserem Fall $n+1$) springen und zeigen, dass der Beweis für das nachfolgende
Element erbracht werden kann. Dabei müssen wir unbedingt die Annahme (die Induktionshypothese) verwenden, sonst handelt es sich bei unserem Beweis nicht um eine vollständige
Induktion und sehr wahrscheinlich ist der Beweis dann auch nicht fehlerfrei.
Wir wollen nun also beweisen: $\tforall i \leq n+1: T_i$.
Laut Induktionshypothese gilt: $\tforall i \leq n: T_i$.
Es bleibt daher nur zu beweisen übrig: $T_{n+1}$.
Dazu versuchen wir nun umzuformen:
\begin{align*}
T_{n+1} \lra T_{n} \tag{laut Aussage $A$}
\end{align*}
$T_n$ gilt laut Induktionshypothese, der Beweis ist damit erbracht: Wir haben bewiesen, dass $\tforall i: T_i$.
Diesen Teil der Induktion nennen wir \textbf{Induktionsschritt}.
Meist ist hier mehr Arbeit erforderlich als bei diesem kleinen Beispiel. Wir werden das auch beim nächsten Beispiel sehen.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
Halten wir fest: Die \textbf{vollständige Induktion} besteht aus 3 Einzelschritten: In der \textbf{Induktionsbasis} werden ein oder mehrere Basisfälle direkt bewiesen.
In der \textbf{Induktionshypothese} wird versucht eine allgemeine Aussage (eine Hypothese) zu treffen von der angenommen wird, dass sie bis zum $n$-ten Fall gilt.
Im \textbf{Induktionsschritt} gehen wir einen Schritt weiter, also in den Fall $n+1$ und versuchen diesen zu beweisen. Hier muss unbedingt auf die Induktionshypothese zurückgegriffen
werden, sonst wurde keine vollständige Induktion durchgeführt. Um eine Induktion durchführen zu können müssen die Elemente unbedingt aufzählbar sein
(d.h. man muss eine eindeutige Reihenfolge/Sortierung für die Elemente angeben können).
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Wir wollen zeigen, dass alle ganzen Zahlen durch einen variablenfreien Term dargestellt werden können.
Bevor wir die Induktion durchführen versuchen wir ein Muster zu erkennen.
\begin{align*}
\I{T}{\omega}{null}&=0 \tag{trivial}\\
\I{T}{\omega}{eins}&=1 \tag{trivial}\\
\I{T}{\omega}{plus(eins,eins)}&=2 \tag{eine Addition}\\
\I{T}{\omega}{plus(eins,plus(eins,eins))}&=3 \tag{verschachtelte Addition}
\end{align*}
Wir erkennen das Muster: Alle Zahlen $\in \N$ können durch rekursive Addition von 1 dargestellt werden.
Diese Rekursion kann beliebig tief werden, wir bauen sie allerdings immer in der gleichen Form (nur rechter Ast rekursiv).
Wir definieren uns einen Platzhalter $t_k$ um beliebig lange solcher Ausdrücke einfach darzustellen:
\begin{align*}
t_2 &= \u{plus(eins,eins)} \\
t_3 &= \u{plus(eins,plus(eins,eins))} \\
&\vdots \\
t_{k+1} &= \u{plus(eins,}t_{k}\u{)} \\
\end{align*}
$k$ entspricht der Anzahl der ${\tueins}$ im Ausdruck.
\begin{\whichitem}
\item \textbf{Induktionsbasis:} \quad
In der Induktionsbasis beweisen wir einen oder mehrere Basisfälle.
Das sind in unserem Fall die beiden Konstanten sowie der Fall $t_2$:
\begin{align*}
\I{T}{\omega}{null}&=0 \\
\I{T}{\omega}{eins}&=1 \\
\Iu{T}{\omega}{t_2}&=\I{T}{\omega}{plus(eins,eins)}=2\\
\end{align*}
\item \textbf{Induktionshypothese:} \quad $\Iu{T}{\omega}{t_n}=n$
\item \textbf{Induktionsschritt:}\\
\begin{align*}
\Iu{T}{\omega}{t_{n+1}}&=n+1 \tag{Einsetzen von $t_{n+1}$}\\
\Iu{T}{\omega}{\u{plus(eins,}t_{n}\u{)}}&=n+1 \tag{Interpretationsfunktion durchführen}\\
+\rbr{\Iu{T}{\omega}{{\tueins}},\Iu{T}{\omega}{t_{n}}}&=n+1 \\
+\rbr{1,\Iu{T}{\omega}{t_{n}}}&=n+1
\intertext{\textbf{Unter Verwendung der Induktionshypothese (d.h. wir setzen die Induktionshypothese $\Iu{T}{\omega}{t_n}=n$ ein):}}
+\rbr{1,n}&=n+1
\end{align*}
Damit ist der Beweis erbracht.
\end{\whichitem}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\section{Sprache der Konditionale COND ($\lng{C}$)}
Wir hatten in der Sprache der Terme $\lng{T}$ noch nicht die Möglichkeit Prädikate zu nutzen obwohl Datentypen über
Prädikate verfügen. Dazu definieren wir die Sprache der Konditionale \textbf{COND}. Wir schreiben in diesem Skriptum großteils
nur $\lng{C}$ zwecks Übersichtlichkeit - $\lng{C}$ gesprochen ``COND''.
\begin{defn}[Die Sprache COND ($\lng{C}$)]\label{defn:semcond}
Die Syntax von $\lng{C}$ ist wie folgt definiert:
\begin{\whichenum}
\item $\lng{T} \subseteq \lng{C}$, d.h. alle Terme sind Konditionale.
\item Wenn $p^{\Sigma}_i$ ein $n$-stelliges Prädikatensymbol ist und $u_1,\ldots,u_n,t_1,t_2$ Konditionale,
dann ist auch \; ${\tuif} p_i^{\Sigma}\u{(}u_1\u{,}\ldots\u{,}u_n\u{)}{\tuthen} t_1 {\tuelse} t_2$ \; ein Konditional.
\end{\whichenum}
Die Semantikfunktion $I_{\lng{C}}$ definieren wir durch:
\begin{\whichenum}
\item $\Iu{C}{\omega}{t} = \Iu{T}{\omega}{t}$, wenn $t \in \lng{T}$ und $\omega \in \text{ENV}$.
\item Für jedes Prädikat $p_i$ gilt:
\begin{\whichitem}
\item Wenn $p_i\rbr{\Iu{C}{\omega}{u_1},\ldots,\Iu{C}{\omega}{u_n}}=T$, dann gilt:
\[\Iu{C}{\omega}{{\tuif} p_{i}^{\Sigma} \u{(} u_1\u{,}\ldots\u{,}u_n\u{)}{\tuthen} t_1 {\tuelse} t_2}=\Iu{C}{\omega}{t_1}\]
\item Sonst ist $p_i\rbr{\Iu{C}{\omega}{u_1},\ldots,\Iu{C}{\omega}{u_n}}=F$ und dann gilt:
\[\Iu{C}{\omega}{{\tuif} p_{i}^{\Sigma} \u{(} u_1\u{,}\ldots\u{,}u_n\u{)}{\tuthen} t_1 {\tuelse} t_2}=\Iu{C}{\omega}{t_2}\]
\end{\whichitem}
\end{\whichenum}
\end{defn}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Interpretieren Sie \u{if ist0?(sub(x)) then add0(x) else sub(x)} in $\lng{C}$ über dem Datentyp der binären Stacks mit dem Environment $\omega(\u{x})=101$.
Wir beginnen wie auch schon in der Sprache der Terme.
\begin{align*}
&\quad \I{C}{\omega}{if ist0?(sub(x)) then add0(x) else sub(x)}
\intertext{\textcolor{darkblue}{NR: An dieser Stelle müssen wir nun eine Nebenrechnung (NR) durchführen um zu bestimmen ob der $then$- oder der $else$-Zweig ausgeführt wird.\newline
$\I{C}{\omega}{ist0?(sub(x))}$
$=\text{ist0?}\rbr{\I{C}{\omega}{sub(x)}}$
$=\text{ist0?}\rbr{\text{sub}\rbr{\I{C}{\omega}{x}}}$ \newline
$\underbrace{=\text{ist0?}\rbr{\text{sub}\rbr{\I{T}{\omega}{x}}}}_{\text{trivial \tto meist nicht angeschrieben}}$
$=\text{ist0?}\rbr{\text{sub}\rbr{\omega\rbr{\u{x}}}}$
$=\text{ist0?}\rbr{\text{sub}\rbr{101}}$
$=\text{ist0?}\rbr{01} = T$}}
&= \I{C}{\omega}{add0(x)} \tag{folgt aus der NR} \\
&= \text{add0}\rbr{\I{C}{\omega}{x}} = \text{add0}\rbr{\omega\rbr{\u{x}}} = \text{add0}\rbr{101} = 0101
\end{align*}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
Bei Verschachtelungen von Prädikaten in $\lng{C}$ ist zu beachten, dass Prädikate direkt kein Teil der Sprache sind.
Daher ist auch der Ausdruck \u{if ist0?(ist1?(x)) then x else add0(x)} nicht in $\lng{C}$!
Allerdings ist \u{if ist0?(if ist1?(x) then 110 else 010) then x else add0(x)} in $\lng{C}$.
\section{Rekursionen - Sprache der Ausdrücke EXP ($\lng{E}$)}
Bisher war es nicht möglich Funktionen (insbesondere rekursive) zu definieren. Wir müssen das Konzept ``Funktionsname''
ähnlich wie die Variablennamen (IVS, Individuenvariablensymbole) zuerst einführen.
Der Wert der einem Funktionsnamen zugeordnet wird ist dabei ein Programm.
Wir definieren nun die Sprache \textbf{EXP} ($\lng{E}$). Wie schon bei \textbf{COND} kürzen wir auch hier \textbf{EXP} durch $\lng{E}$ ab - $\lng{E}$ gesprochen ``EXP''.
\begin{defn}
Die Menge der Funktionsvariablensymbole (FVS) enthält ``Namen'' aller Funktionen.
\end{defn}
\begin{defn}
Die Menge der Funktionsenvironments bezeichnen wir mit FENV.
Jedes Funktionsenvironment $\delta: \text{FVS} \to \lng{E}$ liefert für ein Funktionsvariablensymbol die
Implementation in EXP ($\lng{E}$) zurück. $\delta\u{X}$ bezeichne die Implementation der Funktion mit dem Namen $\u{X}$.
\end{defn}
Es muss unbedingt unterschieden werden zwischen
\begin{\whichitem}
\item Funktionen des Datentyps ($+$, $-$, etc.) sowie den dazugehörigen Funktionssymbolen (\u{plus}, \u{minus}, etc.)
\item und ``benutzerdefinierten Funktionen'', d.h. Unterprogramme die auch in der Sprache implementiert werden. Diese bezeichnen wir als Funktionsvariablensymbole.
\end{\whichitem}
\begin{defn}[Syntax von EXP ($\lng{E}$)]
Die Syntax von $\lng{E}$ ist definiert wie folgt:
\begin{\whichitem}
\item $\lng{C} \subseteq \lng{E}$, d.h. alle Konditionale sind Ausdrücke (d.h. $\in \lng{E}$).
\item Wenn $f$ eine $n$-stellige Funktionenvariable ($\in$ FVS)
ist und $t_1,\ldots,t_n$ sind Ausdrücke (d.h. $\in \lng{E}$),
dann ist $f\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}$ ein Ausdruck (d.h. $\in \lng{E}$).
\end{\whichitem}
\end{defn}
Eine Funktion kann also über die Parameter hinaus keine weiteren Variablen haben.
Beim Funktionsaufruf werden Parameter übergeben. Wir behandeln dabei zunächst nur call-by-value.
Hierbei werden die als Parameter übergebenen Ausdrücke \textbf{vor} Ausführung der Funktion
berechnet (interpretiert) und die Variablen der Funktion werden in einem neuen Variablenenvironment
auf die entsprechenden Werte initialisiert.
\begin{defn}[Semantik von EXP ($\lng{E}$)]\label{defn:semexp}
Die Semantikfunktion $I_{\lng{E}}$ definieren wir durch:
\begin{\whichenum}
\item $\Iu{E}{\delta,\omega}{c} = \Iu{C}{\omega}{c}$, wenn $c \in \lng{C}$ und $\omega \in \text{ENV}$.
\item $\Iu{E}{\delta,\omega}{F\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}}$ mit $F \in \text{FENV}$. Funktionsaufruf mit call-by-value:
\begin{\whichenum}
\item Definiere $\omega'$ als neues Environment mit $\omega'(x_i)=\Iu{E}{\delta,\omega}{t_i}$ (für $1 \leq i \leq n$) wobei $x_i$
die Parameter der Funktion $\delta F$ sind. Im Normalfall ist $x_i=\u{xi}$, d.h. $x_1=\u{x1}$, $x_2=\u{x2}$, usw.
\item $\Iu{E}{\delta,\omega}{F\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}}=\Iu{E}{\delta,\omega'}{\delta F}$
\end{\whichenum}
\end{\whichenum}
\end{defn}
\begin{anm}
Mit den Definitionen \ref{defn:semt}, \ref{defn:semcond} und \ref{defn:semexp} halten wir zwecks Übersicht fest:
\begin{\whichenum}
\item $I_{\lng{T}}(\omega,c^{\Sigma}_i)=c_i$ mit $c_i \in C$ (Semantik-Ebene), $c^{\Sigma}_i \in C^{\Sigma}$ (Syntax-Ebene) und $\omega \in \text{ENV}$.
\item $I_{\lng{T}}(\omega,v)=\omega(v)$ mit $v \in \text{IVS}$ und $\omega \in \text{ENV}$.
\item $I_{\lng{T}}(\omega,f^{\Sigma}_i\u{(}t_1\u{,}\ldots\u{,}t_n\u{)})=f_i(I_{\lng{T}}(\omega,t_1),\ldots,I_{\lng{T}}(\omega,t_n))$ mit $f_i \in F$ (Semantik-Ebene), $f^{\Sigma}_i \in F^{\Sigma}$ (Syntax-Ebene) und $\omega \in \text{ENV}$.
\item $\Iu{E}{\delta,\omega}{t} = \Iu{T}{\omega}{t}$, wenn $t \in \lng{T}$ und $\omega \in \text{ENV}$ und $\delta \in \text{FENV}$.
\item Für jedes Prädikat $p_i$ gilt:
\begin{\whichitem}
\item Wenn $p_i\rbr{\Iu{C}{\omega}{u_1},\ldots,\Iu{C}{\omega}{u_n}}=T$, dann gilt:
\[\Iu{C}{\omega}{{\tuif} p_{i}^{\Sigma} \u{(} u_1\u{,}\ldots\u{,}u_n\u{)}{\tuthen} t_1 {\tuelse} t_2}=\Iu{C}{\omega}{t_1}\]
\item Sonst ist $p_i\rbr{\Iu{C}{\omega}{u_1},\ldots,\Iu{C}{\omega}{u_n}}=F$ und dann gilt:
\[\Iu{C}{\omega}{{\tuif} p_{i}^{\Sigma} \u{(} u_1\u{,}\ldots\u{,}u_n\u{)}{\tuthen} t_1 {\tuelse} t_2}=\Iu{C}{\omega}{t_2}\]
\end{\whichitem}
\item $\Iu{E}{\delta,\omega}{F\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}}$ mit $F \in \text{FENV}$. Funktionsaufruf mit call-by-value:
\begin{\whichenum}
\item Definiere $\omega'$ als neues Environment mit $\omega'(x_i)=\Iu{E}{\delta,\omega}{t_i}$ (für $1 \leq i \leq n$) wobei $x_i$
die Parameter der Funktion $\delta F$ sind. Im Normalfall ist $x_i=\u{xi}$, d.h. $x_1=\u{x1}$, $x_2=\u{x2}$, usw.
\item $\Iu{E}{\delta,\omega}{F\u{(}t_1\u{,}\ldots\u{,}t_n\u{)}}=\Iu{E}{\delta,\omega'}{\delta F}$
\end{\whichenum}
\end{\whichenum}
\end{anm}
Wir definieren eine Funktion \u{func} in $\lng{E}$ durch $\delta\tu{func}=\u{\ldots}$.
Im Rahmen der Übung ist es auch zulässig bei der Funktionsdefinition explizit andere Parameter anzugeben ($\delta\tu{func(x,v)}=\u{\ldots}$)
um die Parameternamen festzulegen. In unserem Fall wäre dann $x_1 = \u{x}$ und $x_2 = \u{v}$.
Die Komplexität des $\lng{E}$-Interpreters wird dadurch nicht wesentlich beeinflusst.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Interpretieren Sie das Programm \u{F(sub(x))} in $\lng{E}$ über dem Datentyp der Stacks, wobei $\delta\u{F}=$\u{if ist0?(x1) then sub(x1) else add1(x1)} und
$\omega(\u{x})=100$.
\textit{Lösung:}
\begin{align*}
\I{E}{\delta,\omega}{F(sub(x))}
\intertext{\textcolor{darkblue}{Neues Environment (NE): $\omega'(\tu{x1})=\I{E}{\delta,\omega}{\text{sub}(x)}=\text{sub}(\I{E}{\delta,\omega}{x})=\text{sub}(\omega(\u{x}))=\text{sub}(100)=00$}}
&= \I{E}{\delta,\omega'}{\text{if ist0?(x1) then sub(x1) else add1(x1)}} \\
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega'}{\text{ist0?(x1)}}=\text{ist0?}(\I{E}{\delta,\omega'}{x1})=\text{ist0?}(\omega'(\tu{x1}))=\text{ist0?}(00)=T$}}
&= \I{E}{\delta,\omega'}{\text{sub(x1)}} \\
&= \text{sub}(\I{E}{\delta,\omega'}{\text{x1}}) \\
&= \text{sub}(\omega'(\tu{x1})) \\
&= \text{sub}(00) \\
&= 0
\end{align*}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
Im Vorlesungsskriptum findet sich außerdem auf Seite 59 die Definition für Funktionsaufrufe mittels Call-by-Name sowie obiges Beispiel für Call-by-Name durchgerechnet.
Außerdem wird demonstriert, dass es Funktionen gibt (die in Teilbereichen undefiniert sind) die je nach Verfahren ein unterschiedliches Verhalten zeigen.
\ifthenelse{\boolean{long}}{}{\begin{comment}}
Wir haben bereits die vollständige Induktion kennengelernt. Mittels vollständiger Induktion können wir auch die Korrektheit von Programmen in $\lng{E}$
beweisen.
\begin{bsp}
Gegeben sei der Datentyp der nicht-negativen Integer der nur die Funktionen Inkrement um 1 (\u{inc}) und Dekrement um 1 (\u{dec}), sowie die bereits bekannten
Prädikate \u{eq?} und \u{gt?}. Implementieren Sie die Addition zweier Zahlen in $\lng{E}$.
\textit{Lösung:}
Um eine Funktion zu schreiben macht es oft Sinn sich zunächst mathematisch aufzuschreiben wie die Funktion definiert ist.
\[\text{add}(x,y)=\begin{cases} y & \text{ wenn } x=0 \\ \text{add}(\text{dec}(x),\text{inc}(y)) & \text{sonst}\end{cases}\]
Aus dieser Darstellung kann direkt das $\lng{E}$ Programm implementiert werden:
\[\delta\tu{add}=\tu{if eq?(x,0) then y else add(dec(x),inc(y))} \qquad \text{(mit Parametern $x_1 = \u{x}, x_2 = \u{y}$)}\]
Um einen Beweis zu führen brauchen wir nun noch ein ``Golden Device'', eine mathematische Funktion die das geforderte Verhalten korrekt berechnet. Diese
kann für den Beweis einfach als gegeben angenommen werden.
In unserem Fall ist es der Operator $+$ über $\N_0$.
Zu zeigen ist also: $\tforall \omega: \I{E}{\delta,\omega}{add(x,y)}=\omega(\u{x})+\omega(\u{y})$
\begin{\whichitem}
\item Induktionsbasis: Sei $\omega(\u{x})=0$ und $\omega(\u{y})=m$ ($m$ beliebig).
\begin{align*}
\I{E}{\delta,\omega}{add(x,y)}
\intertext{\textcolor{darkblue}{Neues Environment? $\omega'(\u{x})=\omega(\u{x})$, $\omega'(\u{y})=\omega(\u{y})$, d.h. es wäre $\omega'=\omega$. Es gilt Gleichheit, daher ist es völlig egal
ob hier $\omega'$ eingeführt wird oder nicht. Dieser Fall tritt immer dann auf wenn die Aufruf-Parameter gleich den Funktionsparametern aus der Definition sind. In diesen Fällen führen wir in diesem Skriptum zwecks Übersichtlichkeit keine neuen Environments ein.}}
&= \I{E}{\delta,\omega}{\text{if eq?(x,0) then y else add(dec(x),inc(y))}}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega}{\text{eq?}(x,0)}=\text{eq?}(\I{E}{\delta,\omega}{x},\I{E}{\delta,\omega}{0})=\text{eq?}(\omega(\u{x}),0)=\text{eq?}(0,0)=T$}}
&= \I{E}{\delta,\omega}{y} \\
&= \omega(\u{y}) \\
&= m \\
&= \omega(\u{x})+\omega(\u{y})
\end{align*}
Der Basisfall wurde damit bewiesen.
\item Induktionshypothese: $\I{E}{\delta,\omega}{add(x,y)}=\omega(\u{x})+\omega(\u{y})$ gilt für $\omega(\u{x})=n$ und $\omega(\u{y})=m$ ($m$ beliebig)
\item Induktionsschritt: Zu zeigen ist $\I{E}{\delta,\omega}{add(x,y)}=\omega(\u{x})+\omega(\u{y})$ für $\omega(\u{x})=n+1$ und $\omega(\u{y})=m$ ($m$ beliebig):
\begin{align*}
\I{E}{\delta,\omega}{add(x,y)}
&= \I{E}{\delta,\omega}{\text{if eq?(x,0) then y else add(dec(x),inc(y))}}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega}{\text{eq?}(x,0)}=\text{eq?}(\I{E}{\delta,\omega}{x},\I{E}{\delta,\omega}{0})=\text{eq?}(\omega(\u{x}),0)=\text{eq?}(n+1,0)=F$, da $n \in \N_0$ und folglich $n+1 \geq 1$}}
&= \I{E}{\delta,\omega}{\text{add(dec(x),inc(y))}}
\intertext{\textcolor{darkblue}{NE: $\omega'(\u{x})=\I{E}{\delta,\omega}{\text{dec(x)}}=\text{dec}(\I{E}{\delta,\omega}{\text{x}})=\text{dec}(\omega(\u{x}))=\text{dec}(n+1)=n$, \newline
$\omega'(\u{y})=\I{E}{\delta,\omega}{\text{inc(y)}}=\text{inc}(\I{E}{\delta,\omega}{\text{y}})=\text{inc}(\omega(\u{y}))=\text{inc}(m)=m+1$}}
&= \I{E}{\delta,\omega'}{\text{add(x,y)}} \tag{Wir ersetzen zunächst nur $\omega$!} \\
\intertext{Für diesen Fall ($\omega'(\u{x})=n$) gilt die Induktionshypothese!
Wir sehen, dass der obige Aufruf der Interpretationsfunktion exakt so aussieht wie in der Induktionshypothese.
Unter Verwendung der Induktionshypothese (d.h. wir setzen die Induktionshypothese $\I{E}{\delta,\omega}{add(x,y)}=\omega(\u{x})+\omega(\u{y})$ ein):}
&= \omega'(\u{x})+\omega'(\u{y}) \\
&= n+m+1 \\
&= \omega(\u{x})+\omega(\u{y})
\end{align*}
Wir haben also bewiesen $\I{E}{\delta,\omega}{add(x,y)} = \ldots = \omega(\u{x})+\omega(\u{y})$. Das ist exakt
die Gleichheit die wir für den Beweis der Korrektheit zeigen mussten.
\end{\whichitem}
Im obigen Beweis haben wir folgende Umformung durchgeführt:
\begin{align*}
&\quad \I{E}{\delta,\omega}{\text{add(dec(x),inc(y))}}
\intertext{\textcolor{darkblue}{NE: $\omega'(\u{x})=n$, $\omega'(\u{y})=m+1$}}
&= \I{E}{\delta,\omega'}{\text{add(x,y)}}
\end{align*}
Diese Abkürzung ist im Rahmen der Übung durchaus erwünscht.
Sie ist zulässig da die Interpretationsfunktion $I_{\lng{E}}$ entsprechend
definiert wurde.
Laut Definition ist
\[\I{E}{\delta,\omega'}{\text{add(x,y)}}=\I{E}{\delta,\omega'}{\text{if eq?(x,0) then y else add(dec(x),inc(y))}}.\]
Daher können wir umformen:
\begin{align*}
&\quad \I{E}{\delta,\omega}{\text{add(dec(x),inc(y))}} \\
&= \I{E}{\delta,\omega'}{\text{if eq?(x,0) then y else add(dec(x),inc(y))}} \\
&= \I{E}{\delta,\omega'}{\text{add(x,y)}}
\end{align*}
Dies ist exakt die Umformung die wir gemacht haben.
Ein Vorteil in dieser Variante liegt darin, dass einfach gesehen werden kann wenn die Induktionshypothese
zutrifft.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
Die Sprache $\lng{E}$ ist von uns konstruiert und in der Praxis nicht relevant.
Funktionale Sprachen (Lisp, Haskell, OCaml, etc.) im Allgemeinen sind allerdings durchaus relevant - und auch angenehmer zu verwenden als $\lng{E}$.
Dadurch, dass wir $\lng{E}$ genau verstehen wird es uns auch leicht fallen neue Sprachen zu erlernen.
Hier ein Vergleich eines rekursiven Programms zum Ermitteln der $n$-ten Fibonacci-Zahl in verschiedenen funktionalen Sprachen:
\begin{\whichitem}
\item EXP:
\begin{verbatim}
fib(n) = if eq?(n,0) then 1
else plus(fib(minus(n,1)),fib(minus(n,2)))
\end{verbatim}
\item Erlang:
\begin{verbatim}
fib(0) -> 1;
fib(n) -> fib(n-1) + fib(n-2)
\end{verbatim}
\item Haskell:
\begin{verbatim}
fib 0 = 1
fib n = fib(n-1) + fib(n-2)
\end{verbatim}
\end{\whichitem}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\section{Datentyp der Listen $\mathcal{L}$}
Der Datentyp der Listen kommt in vielen Sprachen vor. Wir verwenden dazu die Darstellung mit eckigen Klammern und groß geschriebenen
Wörtern ([ APE BEE CAT ]).
\begin{defn}[Atom]
Etwas ist ein Atom genau dann wenn kein [ und kein ] darin vorkommt.
Listenelemente die keine ``echten'' Listen sind (APE, BEE, CAT, etc.) werden Atom genannt.
Alle anderen Listen sind keine Atome.
\end{defn}
\begin{defn}[Datentyp der Listen $\mathcal{L}$] \quad
\begin{\whichitem}
\item Grundmenge $A$:
\begin{\whichitem}
\item ATOM $\subseteq A$, d.h. alle Atome sind Listen
\item $[ ] \subseteq A$, d.h. die leere Liste ist eine Liste
\end{\whichitem}
\item Funktionen
\begin{\whichenum}
\item $f_1: \text{first}$ (liefert das erste Element einer Liste)
\begin{\whichitem}
\item Wenn $a \in \text{ATOM}$, dann ist $\text{first}(a)=[ ]$.
\item $\text{first}([ ])=[ ]$.
\item Wenn $\tforall i, \quad 1 \leq i \leq k: \quad \ell_i \in L$, dann ist $\text{first}([ \ell_1 \ldots \ell_k ])=\ell_1$
\end{\whichitem}
\item $f_2: \text{rest}$ (liefert die Liste ohne das erste Element)
\begin{\whichitem}
\item Wenn $a \in \text{ATOM}$, dann ist $\text{rest}(a)=[ ]$.
\item $\text{rest}([ ])=[ ]$.
\item Wenn $\ell \in L$, dann ist $\text{rest}([\ell])=[ ]$
\item Wenn $\tforall i, \quad 1 \leq i \leq k: \quad \ell_i \in L$ und $k > 1$, dann ist $\text{rest}([ \ell_1 \ell_2 \ldots \ell_k ])=[ \ell_2 \ldots \ell_k ]$
\end{\whichitem}
\item $f_3: \text{build}$ (nimmt 2 Listen entgegen und fügt die eine als erste Element in die andere ein)
\begin{\whichitem}
\item Wenn $a \in \text{ATOM}$ und $\ell \in L$, dann ist $\text{build}(\ell,a)=a$.
\item Wenn $\ell \in L$, $\text{build}(\ell,[ ])=[\ell]$.
\item Wenn $\ell \in L$ und $\tforall i, \quad 1 \leq i \leq k: \quad \ell_i \in L$, dann ist $\text{build}(\ell,[ \ell_1 \ldots \ell_k ])=[ \ell \ell_1 \ldots \ell_k ]$
\end{\whichitem}
\end{\whichenum}
\item Prädikate
\begin{\whichenum}
\item $p_1: \text{atom?}$
\begin{\whichitem}
\item $\text{atom?}(x)=T$, genau dann wenn $x \in \text{ATOM}$
\end{\whichitem}
\item $p_2: \text{eq?}$
\begin{\whichitem}
\item $\text{eq?}(x,y)=T$, genau dann wenn $x=y$
\end{\whichitem}
\end{\whichenum}
\item Konstanten: Die leere Liste ($c_1=[]$ mit $c_1^\Sigma=\tu{nil}$), sowie je eine Konstante für jedes Atom
\end{\whichitem}
Die Symbole auf der syntaktischen Ebene werden entsprechend der zuvor verwendeten Bezeichnungen gewählt (z.B. $p_1^{\Sigma}=\tu{atom?}$).
\end{defn}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Definieren Sie eine Funktion \u{second} in $\lng{E}$ welches immer das 2. Element einer Liste zurückliefert.
Interpretieren Sie ihre Funktion für den Parameter [ FIR SEC THI ].
\textit{Lösung:} Zuerst trennen wir das erste Element von der Liste, anschließend
geben wir das neue erste Element zurück:
\[\delta\tu{second}=\tu{first(rest(x))}\]
\begin{align*}
&\quad \I{E}{\delta,\omega}{\text{second(x)}}
\intertext{\textcolor{darkblue}{Environment bleibt gleich: $\omega(\u{x})=\text{[ FIR SEC THI ]}$}}
&= \I{E}{\delta,\omega}{\text{first(rest(x))}} \\
&= \text{first}\rbr{\I{E}{\delta,\omega}{\text{rest(x)}}} \\
&= \text{first}\rbr{\text{rest}\rbr{\I{E}{\delta,\omega}{\text{x}}}} \\
&= \text{first}\rbr{\text{rest}\rbr{\omega(\tu{x})}} \\
&= \text{first}\rbr{\text{rest}\rbr{\text{[ FIR SEC THI ]}}} \\
&= \text{first}\rbr{\text{[ SEC THI ]}} \\
&= \text{SEC}
\end{align*}
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Definieren Sie eine Funktion \u{reverse} in $\lng{E}$ welches eine Liste elementweise umgedreht zurückliefert.
Interpretieren Sie ihre Funktion für den Parameter [ FIR SEC THI ].
\textit{Lösung:} Bei der Konstruktion rekursiver Programme versuchen wir meist von einem Basisfall ausgehend
komplexere Fälle aufzubauen.
Ein Basisfall ist für uns ein Atom, die leere Liste und Listen mit genau einem Element. Diese können wir unverändert zurückliefern.
Andernfalls haben wir eine Liste mit mehreren Elementen. Dann werden wir das erste (bzw. das letzte) Element von der Liste entfernen und
eine neue Liste bauen die aus dem entfernten Element und dem umgedrehten Rest der Liste besteht. Wir wählen die Variante mit dem ersten Element
da der Datentyp der Listen dies einfach ermöglicht. Um das letzte Element zu erhalten müssten wir den Datentyp modifizieren oder ein Programm schreiben
welches nur das letzte Element zurückliefert.
Wir halten also fest:
\[\text{reverse}(x) = \begin{cases}
x & x \in \text{ATOM} \\
x & x = \ebr{} \\
x & x = \ebr{\ell} \\
\ebr{ \ell_{k} \text{reverse}\rbr{[ \ell_1 \ldots \ell_{k-1} ]}} & x = \ebr{\ell_1 \ldots \ell_{k-1} \ell_k}
\end{cases}\]
Dies können wir wieder nicht direkt als $\lng{E}$-Programm umschreiben. Wir haben in der Sprache keine Möglichkeit
auf das letzte Element einer Liste zuzugreifen. Wir könnten dafür eine Funktion $\delta\tu{last}$ schreiben oder
direkt durch eine Rekursion über die Liste iterieren bis zum letzten Element und
in einem zweiten Parameter (``Akkumulator'') die Liste aufbauen.
\begin{align*}
\delta\tu{reverse(x)}&=\tu{if atom?(x) then x else reverse2(x,nil)} \\
\delta\tu{reverse2(x,y)}&=\tu{if eq?(x,nil) then y else reverse2(rest(x),build(first(x),y))}
\end{align*}
Verhält sich dieses Programm wie beabsichtigt?
\begin{align*}
&\quad \I{E}{\delta,\omega}{reverse(x)} \\
&= \I{E}{\delta,\omega}{if atom?(x) then x else reverse2(x,nil)}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega}{atom?(x)}=\text{atom?}\rbr{\I{E}{\delta,\omega}{x}}=\text{atom?}\rbr{\omega(\tu{x})}$\newline$=\text{atom?}\rbr{\text{[ FIR SEC THI ]}}=F$}}
&= \I{E}{\delta,\omega}{reverse2(x,nil)}
\intertext{\textcolor{darkblue}{NE: $\omega'(\tu{x})=\I{E}{\delta,\omega}{x}=\omega(\tu{x})=\text{[ FIR SEC THI ]}$, $\omega'(\tu{y})=\I{E}{\delta,\omega}{nil}=\text{[]}$}}
&= \I{E}{\delta,\omega'}{reverse2(x,y)} \\
&= \I{E}{\delta,\omega'}{if eq?(x,nil) then y else reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega'}{eq?(x,nil)}=\text{eq?}\rbr{\I{E}{\delta,\omega'}{x},\I{E}{\delta,\omega'}{nil}}=\text{eq?}\rbr{\omega'(\tu{x}),[]}$\newline$=\text{eq?}\rbr{\text{[ FIR SEC THI ]},[]}=F$}}
&= \I{E}{\delta,\omega'}{reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NE: $\omega''(\tu{x})=\I{E}{\delta,\omega'}{rest(x)}=\text{rest}\rbr{\I{E}{\delta,\omega'}{x}}=\text{rest}\rbr{\omega'(\tu{x})}$\newline$=\text{rest}\rbr{\text{[ FIR SEC THI ]}}=\text{[ SEC THI ]}$, \newline
$\omega''(\tu{y})=\I{E}{\delta,\omega'}{build(first(x),y)}=\text{build}\rbr{\I{E}{\delta,\omega'}{first(x)},\I{E}{\delta,\omega'}{y}}$\newline$=\text{build}\rbr{\text{first}\rbr{\I{E}{\delta,\omega'}{x}},\I{E}{\delta,\omega'}{y}}=\text{build}\rbr{\text{first}\rbr{\omega'(\tu{x})},\omega'(\tu{y})}$\newline$=\text{build}\rbr{\text{first}\rbr{\text{[ FIR SEC THI ]}},[]}=\text{build}\rbr{\text{FIR},[]}=\text{[ FIR ]}$}}
&= \I{E}{\delta,\omega''}{reverse2(x,y)} \\
&= \I{E}{\delta,\omega''}{if eq?(x,nil) then y else reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega''}{eq?(x,nil)}=\text{eq?}\rbr{\I{E}{\delta,\omega''}{x},\I{E}{\delta,\omega''}{nil}}$\newline$=\text{eq?}\rbr{\omega''(\tu{x}),[]}=\text{eq?}\rbr{\text{[ SEC THI ]},[]}=F$}}
&= \I{E}{\delta,\omega''}{reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NE: $\omega'''(\tu{x})=\I{E}{\delta,\omega''}{rest(x)}=\text{rest}\rbr{\I{E}{\delta,\omega''}{x}}=\text{rest}\rbr{\omega''(\tu{x})}$\newline$=\text{rest}\rbr{\text{[ SEC THI ]}}=\text{[ THI ]}$, \newline
$\omega'''(\tu{y})=\I{E}{\delta,\omega''}{build(first(x),y)}=\text{build}\rbr{\I{E}{\delta,\omega''}{first(x)},\I{E}{\delta,\omega''}{y}}$\newline$=\text{build}\rbr{\text{first}\rbr{\I{E}{\delta,\omega''}{x}},\I{E}{\delta,\omega''}{y}}=\text{build}\rbr{\text{first}\rbr{\omega''(\tu{x})},\omega''(\tu{y})}$\newline$=\text{build}\rbr{\text{first}\rbr{\text{[ SEC THI ]}},\text{[ FIR ]}}=\text{build}\rbr{\text{SEC},\text{[ FIR ]}}=\text{[ SEC FIR ]}$}}
&= \I{E}{\delta,\omega'''}{reverse2(x,y)} \\
&= \I{E}{\delta,\omega'''}{if eq?(x,nil) then y else reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega'''}{eq?(x,nil)}=\text{eq?}\rbr{\I{E}{\delta,\omega'''}{x},\I{E}{\delta,\omega'''}{nil}}$\newline$=\text{eq?}\rbr{\omega'''(\tu{x}),[]}=\text{eq?}\rbr{\text{[ THI ]},[]}=F$}}
&= \I{E}{\delta,\omega'''}{reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NE: $\omega''''(\tu{x})=\I{E}{\delta,\omega'''}{rest(x)}=\text{rest}\rbr{\I{E}{\delta,\omega'''}{x}}=\text{rest}\rbr{\omega'''(\tu{x})}$\newline$=\text{rest}\rbr{\text{[ THI ]}}=\text{[ ]}$, \newline
$\omega''''(\tu{y})=\I{E}{\delta,\omega'''}{build(first(x),y)}=\text{build}\rbr{\I{E}{\delta,\omega'''}{first(x)},\I{E}{\delta,\omega'''}{y}}$\newline$=\text{build}\rbr{\text{first}\rbr{\I{E}{\delta,\omega'''}{x}},\I{E}{\delta,\omega'''}{y}}=\text{build}\rbr{\text{first}\rbr{\omega'''(\tu{x})},\omega'''(\tu{x})}$\newline$=\text{build}\rbr{\text{first}\rbr{\text{[ THI ]}},\text{[ SEC FIR ]}}=\text{build}\rbr{\text{THI},\text{[ SEC FIR ]}}=\text{[ THI SEC FIR ]}$}}
&= \I{E}{\delta,\omega''''}{reverse2(x,y)} \\
&= \I{E}{\delta,\omega''''}{if eq?(x,nil) then y else reverse2(rest(x),build(first(x),y))}
\intertext{\textcolor{darkblue}{NR: $\I{E}{\delta,\omega''''}{eq?(x,nil)}=\text{eq?}\rbr{\I{E}{\delta,\omega'''}{x},\I{E}{\delta,\omega'''}{nil}}$\newline$=\text{eq?}\rbr{\omega'''(\tu{x}),[]}=\text{eq?}\rbr{[],[]}=T$}}
&= \I{E}{\delta,\omega''''}{y} \\
&= \omega''''(\tu{y}) \\
&= \text{[ THI SEC FIR ]}
\end{align*}
Das Programm verhält sich für diesen Fall wie gewünscht. Um zu beweisen, dass es sich immer korrekt verhält müssten wir einen Beweis führen.
\end{bsp}
\ifthenelse{\boolean{long}}{}{\end{comment}}
\ifthenelse{\boolean{long}}{}{\begin{comment}}
\begin{bsp}
Zeigen oder widerlegen Sie: Es gibt ein Programm in EXP über den Datentyp der Listen,
welches die maximale Verschachtelungs-Tiefe einer Liste berechnet.
Greifen Sie dafür auf die in der Vorlesung besprochene Codierung der natürlichen
Zahlen zurück.
Beispielsweise würde der Aufruf mit dem Input \verb|[]| als Resultat \verb|[]| berechnen,
der Aufruf mit dem Input \verb|[ a [] [ [] b ] [] ]|
würde als Resultat \verb|[[[]]]| berechnen.
Wenn die Aussage wahr ist, ist eine Implementation anzugeben
und die Korrektheit dieser zu zeigen.
\textit{Lösung:} (Aus der Übung 2011) Wir haben im Tutorium das Programm zur Berechnung der maximalen Verschachtelungstiefe wie folgt implementiert:
\begin{align*}
\delta\u{\text{depth}}&=\u{\text{if atom?(first(x)) then depth(rest(x))}} \\ &\quad \u{\text{else if eq?(x,nil) then nil}} \\ &\quad \u{\text{else max(build(depth(first(x)),nil),depth(rest(x)))}} \\
\delta\u{\text{max}}&=\u{\text{if eq?(x,nil) then y}} \\ &\quad \u{\text{else if eq?(y,nil) x}} \\ &\quad \u{\text{else build(max(rest(x),rest(y)),nil)}}
\end{align*}
Die Korrektheit von $\delta\u{\text{max}}$ wurde im Tutorium per Induktion gezeigt, dem geneigten Leser ist es überlassen diesen Beweis selbst durchzuführen.
Wir haben $f_{d}(\omega(\u{x}))$ als ``Golden Device'' definiert, eine Funktion ($L \to \N$) die die gesuchte Funktion korrekt berechnet.
Bei einer Induktion wollen wir im Allgemeinen von einem Fall auf den nächsten bzw. nachfolgenden schließen.
In unserem Fall ist das gar nicht so leicht, denn die Listen sind beliebig verschachtelt.
Wenn wir z.B. die Listenlänge $n$ verwenden, könnte im rekursiven Aufruf die Länge der Liste $\text{first}(\omega(\u{x}))$ größer als $n$ sein.
Ein Umweg über die Listentiefe $t$ ist eher umständlich.
In so einem Fall ist es recht hilfreich sich zu überlegen ob es ein anderes Kriterium gibt, mit welchem wir beide
Rekursionsaufrufe auf die Hypothese zurückführen können.
Daher erfolgt der Beweis für $\delta\u{\text{depth}}$ mit $\text{atom?}(\text{first}(\omega(\u{x})))=F$ per Induktion nach der Gesamtanzahl $\abs{\omega(\u{x})}$ der Elemente in $\omega(\u{x})$.
Über diese Hilfsfunktion können wir relativ einfach nach dem Schema arbeiten welches in den anderen Beispielen bereits vorkam.
Wir definieren:
\[\abs{\omega(\u{x})} = \begin{cases}1 & \text{eq?}(\omega(\tu{x}),[]) \\
1 & \text{atom?}(\omega(\tu{x}),[]) \\
\abs{\text{first}(\omega(\tu{x}))}+\abs{\text{rest}(\omega(\u{x}))} & \text{sonst}\end{cases}\]
Die Idee - mit der wir die Induktion durchführen - könnte man schreiben als:
Wenn $\delta\u{\text{depth}}$ korrekt ist für $\abs{\omega(\u{x})}=n$ ($n \in \N$),
dann ist $\delta\u{\text{depth}}$ auch korrekt für $\abs{\omega(\u{x})}=n+1$.
Induktionshypothese:
\[\forall \omega(\u{x}) \in L, \quad \abs{\omega(\u{x})} \leq n : \quad I(\delta,\omega,\tu{depth(x)}) = f_{d}(\omega(\u{x}))\]
Induktionsbasis:
\[\omega(\u{x}) \in L, \abs{\omega(\u{x})} = 1\]
\begin{align*}
&&\quad I(\delta,\omega,&\u{\text{depth(x)}}) \\
&&=I(\delta,\omega,&\u{\text{if atom?(first(x)) then depth(rest(x))}} \\ &&&\u{\text{else if eq?(x,nil) then nil}} \\ &&&\u{\text{else max(build(depth(first(x)),nil),depth(rest(x)))}})
\intertext{\textcolor{darkblue}{NR: $I(\delta,\omega,\u{\text{atom?(first(x))}})=\text{atom?}(I(\delta,\omega,\u{\text{first(x)}}))=\text{atom?(first}(I(\delta,\omega,\u{\text{x}})))$\newline$=\text{atom?(first([]))}=\text{atom?([])}=F$ (da dies zu einer Rekursion führen würde und folglich kein Basisfall ist.)}}
&&=I(\delta,\omega,&\u{\text{if eq?(x,nil) then nil}} \\ &&&\u{\text{else max(build(depth(first(x)),nil),depth(rest(x)))}})
\intertext{\textcolor{darkblue}{Da $\abs{\omega(\u{x})}=1$ ist muss $\omega(\u{x})=\text{[]}$ sein.}}
&&=I(\delta,\omega,&\u{\text{nil}})=\text{[]}=f_{d}(\text{[]})=f_{d}(\omega(\u{x}))
\end{align*}
Induktionsschritt:
\[\omega(\u{x}) \in L, \abs{\omega(\u{x})} = n+1, n \in \N\]
\begin{align*}
&&\quad I(\delta,\omega,&\u{\text{depth(x)}}) \\
&&=I(\delta,\omega,&\u{\text{if atom?(first(x)) then depth(rest(x))}} \\ &&&\u{\text{else if eq?(x,nil) then nil}} \\ &&&\u{\text{else max(build(depth(first(x)),nil),depth(rest(x)))}})
\end{align*}
Fallunterscheidung nach $atom?(first(\omega(\tu{x})))$:
\begin{itemize}
\item Fall $atom?(first(\omega(\tu{x})))=T$
\begin{align*}
\intertext{\textcolor{darkblue}{NR: $I(\delta,\omega,\u{\text{atom?(first(x))}})=\text{atom?}(I(\delta,\omega,\u{\text{first(x)}}))=\text{atom?(first}(I(\delta,\omega,\u{\text{x}})))=T$ (siehe Fallunterscheidung)}}
&&=I(\delta,\omega,&\u{\text{depth(rest(x))}})
\intertext{\textcolor{darkblue}{$\omega'(\tu{x})=I(\delta,\omega,\u{\text{rest(x)}})=\text{rest}(I(\delta,\omega,\u{\text{x}}))=\text{rest}(\omega(\u{x}))$. Die Gesamtanzahl der Elemente dieser Liste ist mindestens um $1$ geringer, da $\text{first}(x)$ aus der Liste entfernt wurde.}}
&&=I(\delta,\omega',&\u{\text{depth(x)}})
\intertext{\textcolor{darkblue}{Für dieses Environment gilt die Induktionshypothese. Wir wenden die Induktionshypothese daher an:}}
&&=&f_{d}(\omega'(\tu{x})) \\
&&=&f_{d}(\text{rest}(\omega(\u{x})))
\intertext{\textcolor{darkblue}{Was korrekt ist, da das Atom $first(\omega(\tu{x}))$ die Listentiefe nicht beeinflusst.}}
\end{align*}
\item Fall $atom?(first(\omega(\tu{x})))=F$
\begin{align*}
\intertext{\textcolor{darkblue}{NR: $I(\delta,\omega,\u{\text{atom?(first(x))}})=\text{atom?}(I(\delta,\omega,\u{\text{first(x)}}))=\text{atom?(first}(I(\delta,\omega,\u{\text{x}})))=F$ (siehe Fallunterscheidung)}}
&&=I(\delta,\omega,&\u{\text{if eq?(x,nil) then nil}} \\ &&&\u{\text{else max(build(depth(first(x)),nil),depth(rest(x)))}})
\intertext{\textcolor{darkblue}{Da $\abs{\omega(\u{x})}>1$ ist, ist $\omega(\u{x})\neq\text{[]}$}}
&&=I(\delta,\omega,&\u{\text{max(build(depth(first(x)),nil),depth(rest(x)))}})
\intertext{\textcolor{darkblue}{Korrektheit von $\delta\u{\text{max}}$ wurde bereits gezeigt}}
&&=&\text{max}(I(\delta,\omega,\u{\text{build(depth(first(x)),nil)}}),I(\delta,\omega,\u{\text{depth(rest(x))}})) \\
&&=&\text{max}(\text{build}(I(\delta,\omega,\u{\text{depth(first(x))}}),\text{[]}),I(\delta,\omega,\u{\text{depth(rest(x))}}))
\intertext{\textcolor{darkblue}{$\omega''(\u{x})=I(\delta,\omega,\u{\text{first(x)}})=\text{first}(I(\delta,\omega,\u{\text{x}}))=\text{first}(\omega(\u{x}))$. Die Gesamtanzahl der Elemente dieser Liste ist mindestens um $1$ geringer, da die Eltern-Liste nicht im rekursiven Aufruf enthalten ist.}}
\intertext{\textcolor{darkblue}{$\omega'''(\u{x})=I(\delta,\omega,\u{\text{rest(x)}})=\text{rest}(I(\delta,\omega,\u{\text{x}}))=\text{rest}(\omega(\u{x}))$. Die Gesamtanzahl der Elemente dieser Liste ist mindestens um $1$ geringer, da $\text{first}(x)$ aus der Liste entfernt wurde.}}
&&=&\text{max}(\text{build}(I(\delta,\omega'',\u{\text{depth(x)}}),\text{[]}),I(\delta,\omega''',\u{\text{depth(x)}}))
\intertext{\textcolor{darkblue}{Damit haben wir für beide rekursiven Aufrufe jeweils ein Environment für, dass die Induktionshypothese gilt. Wir wenden die Induktionshypothese daher an:}}
&&=&\text{max}(\text{build}(f_{d}(\omega''(\u{x})),\text{[]}),f_{d}(\omega'''(\u{x}))) \\
&&=&\text{max}(\text{build}(f_{d}(\text{first}(\omega(\u{x}))),\text{[]}),f_{d}(\text{rest}(\omega(\u{x}))))
\end{align*}
\end{itemize}
Die maximale Verschachtelungstiefe kann nur in $\text{first}(\omega(\u{x}))$ oder $\text{rest}(\omega(\u{x}))$ erreicht werden.
Daher machen wir eine Fallunterscheidung die diese beiden Fälle unterscheidet (und damit alle Fälle abdeckt):
\begin{itemize}
\item Wird die maximale Verschachtelungstiefe $k$ (Anmerkung: $f_{d}(\omega(\u{x}))=\pi(k)$) in $\omega(\u{x})$ in $\text{first}(\omega(\u{x}))$ erreicht
so ist $f_{d}(\omega'(\tu{x}))=\pi(k-1)$, da $\omega'(\tu{x})$ eine Verschachtelungsebene weniger enthält (die der Eltern-Liste).