;; Die ersten drei Zeilen dieser Datei wurden von DrRacket eingefügt. Sie enthalten Metadaten ;; über die Sprachebene dieser Datei in einer Form, die DrRacket verarbeiten kann. #reader(lib "DMdA-vanilla-reader.ss" "deinprogramm")((modname symbdiff) (read-case-sensitive #f) (teachpacks ()) (deinprogramm-settings #(#f write repeating-decimal #f #t none explicit #f ()))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Symbolisches Differenzieren von Funktionen ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require "listoperations.rkt") ; Eine Funktionsanwendung besteht aus ; - einem Funktionsnamen (string) ; - einer Argumentliste (define-record-procedures fun-app make-fun-app fun-app? (fun-app-name fun-app-args)) ; Ein Funktionsausdruck ist eins der folgenden: ; - eine Konstante (real) ; - eine Variable (string) ; - eine Funktionsanwendung (fun-app) (define fun-exp (signature (mixed real string fun-app))) (: make-fun-app (string (list-of fun-exp) -> fun-app)) (: fun-app? (any -> boolean)) (: fun-app-name (fun-app -> string)) (: fun-app-args (fun-app -> (list-of fun-exp))) ; Ist das Argument eine Konstante? (: constant? (any -> boolean)) (define constant? (lambda (x) (real? x))) ; Ist das Argument eine Variable? (: variable? (any -> boolean)) (define variable? (lambda (x) (string? x))) ; Ist das Argument die Summe zweier Funktionen? (: sum? (any -> boolean)) (define sum? (lambda (x) (if (fun-app? x) (string=? (fun-app-name x) "+") #f))) ; Ist das Argument das Produkt zweier Funktionen? (: prod? (any -> boolean)) (define prod? (lambda (x) (if (fun-app? x) (string=? (fun-app-name x) "*") #f))) ; Sind die beiden Argumente identische Variablen? (: equal-variable? (any any -> boolean)) (define equal-variable? (lambda (x y) (and (variable? x) (variable? y) (string=? x y)))) ; Summen und Produkte schöner aufschreiben: (: sum (fun-exp fun-exp -> fun-exp)) #;(define sum (lambda (f1 f2) (make-fun-app "+" (list f1 f2)))) ; Intelligenten Konstruktor, d.h. mit Vereinfachungsregeln (define sum (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (+ f1 f2)) ((constant? f1) (if (= f1 0) f2 (make-fun-app "+" (list f1 f2)))) ((constant? f2) (if (= f2 0) f1 (make-fun-app "+" (list f1 f2)))) (else (make-fun-app "+" (list f1 f2)))))) (: prod (fun-exp fun-exp -> fun-exp)) #;(define prod (lambda (f1 f2) (make-fun-app "*" (list f1 f2)))) (define prod (lambda (f1 f2) (cond ((and (constant? f1) (constant? f2)) (* f1 f2)) ((constant? f1) (cond ((= f1 0) 0) ((= f1 1) f2) (else (make-fun-app "*" (list f1 f2))))) ((constant? f2) (cond ((= f2 0) 0) ((= f2 1) f1) (else (make-fun-app "*" (list f1 f2))))) (else (make-fun-app "*" (list f1 f2)))))) (: axb fun-exp) (define axb (sum (prod "a" "x") "b")) ; Schönere Selektoren: ; Berechne den ersten Operanden einer Funktionsanwendung: (: operand1 (fun-app -> fun-exp)) (define operand1 (lambda (f) (n-th (fun-app-args f) 0))) (: operand2 (fun-app -> fun-exp)) (define operand2 (lambda (f) (n-th (fun-app-args f) 1))) ; Berechne die erste Ableitung eines Funktionsausdrucks: (: derive (fun-exp string -> fun-exp)) (check-expect (derive 42 "x") 0) (check-expect (derive "x" "x") 1) (check-expect (derive "y" "x") 0) (check-expect (derive (sum "x" 3) "x") 1) (check-expect (derive (prod "x" "y") "x") "y") (check-expect (derive axb "x") "a") #;(define derive (lambda (f x) (cond ((constant? f) ...) ((variable? f) ...) ((sum? f) ...) ((prod? f) ...)))) (define derive (lambda (f x) (cond ((constant? f) 0) ((variable? f) (if (equal-variable? f x) 1 0)) ((sum? f) (sum (derive (operand1 f) x) (derive (operand2 f) x))) ((prod? f) (sum (prod (operand1 f) (derive (operand2 f) x)) (prod (operand2 f) (derive (operand1 f) x)))))))