;;; Konstruktion, Vorlesung vom 26.10.2000 ;;; K2 Auswertung mit dem Substitutionsmodell ; Was ist der Wert eines Ausdrucks? ; DEFINITION K1: Substitutionsmodell ; Der Wert eines Literals (Konstante) ist das Literal selbst. ; Sorte number: 4, 17, 42 ; Sorte boolean: #t, #f ; Der Wert eines (lambda (...) ...) ist der Ausdruck selbst. ; Der Wert eines Namens ist der ihn definierende Wert (define). ; Der Wert einer Kombination ( ...) wird ; ermittelt, indem zunächst die Werte des (v0) und der ; en (v1 ... vn) ermittelt werden. ; 1. Falls v0 ein primitiver Operator der Stelligkeit n ist, ; wird seine Definition auf v1 ... vn angewendet. ; 2. Falls v0 = (lambda (x1 ... xn) e), so ist der Wert der ; Kombination der Wert von ; e nach Ersetzung von x1 durch v1 ... xn durch vn. ; Der Wert von (if ) wird ermittelt, ; indem zuerst der Wert v0 von ermittelt wird. ; 1. Falls v0 = #t so ist der Wert des Ausdrucks der Wert von ; ; 2. Falls v0 = #f so ist der Wert des Ausdrucks der Wert von ; ; Anderenfalls: Fehler! ;;; K3 Syntax von Programmen in BNF ; BNF == Backus-Naur-Form ; ::=
* ; ::= ; | ; ::= (define ) ; ::= ; | ; | ; | ; | ; ::= (if ) ; ::= (lambda ) ; ::= (*) ; ::= ; ::= ( *) ; ::= ; ::= ;;; K4 Rekursion und Iteration ; factorial : natural-number -> natural-number ; (factorial n) = n! ; Standarddefinition ; n! = n * (n-1) * ... * 1 ; Induktive Definition ; 0! = 1 ; (n+1)! = (n+1) * n! ; Warum wird hier etwas definiert? ; Funktion auf der rechten Seite braucht nur die Werte der ; Fakultätsfunktion für Zahlen von 0 ... n ; Auf der linken Seite definiert für Werte von 0 ... (n+1) ; Rekursive Definition (define factorial (lambda (n) (if (= n 0) 1 (* n (factorial (- n 1)))))) ; Berechnungsprozess (factorial 3) ((lambda (n) (if (= n 0) 1 (* n (factorial (- n 1))))) 3) (if (= 3 0) 1 (* 3 (factorial (- 3 1)))) (if #f 1 (* 3 (factorial (- 3 1)))) (* 3 (factorial (- 3 1))) (* 3 (factorial 2)) ; ... (* 3 (if (= 2 0) 1 (* 2 (factorial (- 2 1))))) ; ... (* 3 (* 2 (factorial 1))) ; ... (* 3 (* 2 (* 1 (factorial 0)))) ; ... (* 3 (* 2 (* 1 (if (= 0 0) 1 (* 0 (factorial (- 0 1))))))) ; ... (* 3 (* 2 (* 1 1))) 6 ; Warum funktioniert das? ; Aufbau der natürlichen Zahlen ; 1. 0 ist natürliche Zahl ; 2. Falls n natürliche Zahl, dann auch n+1 natürliche Zahl ; 3. Nur die durch 1. und 2. definierten Zahlen sind natürliche Zahlen (define square (lambda (n) (if (= n 0) 0 (+ (square (- n 1)) (- (+ n n) 1))))) ; Korrektheitsbeweis ; Zeige (*): (square n) == (* n n) für alle n in N ; Nachweis von (*) durch vollständige Induktion, entsprechend dem ; Aufbau der natürlichen Zahlen ; 1. Induktionsbeginn ; (*) gilt für n=0 ; (square 0) == 0 == (* 0 0) ; 2. Induktionsschritt ; Falls (*) gilt für n => dann (*) gilt für (n+1) ; (square (+ n 1)) ; == (+ (square (- (+ n 1) 1)) ; (- (+ (+ n 1) (+ n 1)) 1)) ; == (+ (square n) (+ (* 2 n) 1)) ; nach Annahme (square n) == (* n n) ; == (+ (* n n) (+ (* 2 n) 1)) ; nach Binomi ; == (* (+ n 1) (+ n 1)) ; Also: für alle n in N gilt (square n) == (* n n) ;;; Vorlesung vom 31.10.2000 ; Iterative Definition (define it-factorial (lambda (n) (it-factorial-1 n 1))) (define it-factorial-1 (lambda (n result) (if (= n 0) result (it-factorial-1 (- n 1) (* n result))))) ; Berechnungsprozess (it-factorial 3) ((lambda (n) (it-factorial-1 n 1)) 3) (it-factorial-1 3 1) ; Abkürzung: direkt in den Rumpf eingesetzt (if (= 3 0) 1 (it-factorial-1 (- 3 1) (* 3 1))) (it-factorial-1 2 3) (if (= 2 0) 3 (it-factorial-1 (- 2 1) (* 2 3))) (it-factorial-1 1 6) (if (= 1 0) 6 (it-factorial-1 (- 1 1) (* 1 6))) (it-factorial-1 0 6) (if (= 0 0) 6 (it-factorial-1 (- 0 1) (* 0 6))) 6 ; Vergleich mit factorial, Kontext ; Korrektheitsbeweis ; für jeden Aufruf von it-factorial-1 gilt ; n! * result ist konstant (Invariante) ; Falls n>0, so gilt für den rekursiven Aufruf ; (n - 1)! * (n * result) == n * (n-1)! * result == n! * result ; Also: n! == n! * 1 == ... == 0! * result == result ; Oder zeige mit vollständiger Induktion: ; Für alle n in nat ; (**) (it-factorial-1 n r) == n! * r ; 1. Induktionsbeginn ; (**) gilt für n == 0 ; (it-factorial-1 0 r) ; == (if (= 0 0) r (it-factorial-1 ...)) ; == r ; == 1 * r ; == 0! * r ; 2. Induktionsschritt ; Falls (**) gilt für n ==> (**) gilt für n+1 ; (it-factorial-1 (+ n 1) r) ; == (if (= (+ n 1) 0) r (it-factorial (- (+ n 1) 1) (* (+ n 1) r))) ; == (it-factorial n (* (+ n 1) r)) ; { nach Induktionsvoraussetzung: (**) gilt für n } ; == n! * (n+1) * r ; == (n+1)! * r ; { also (**) für n+1 } ; Also : (it-factorial-1 n 1) == n!