SICP 読み (53) 2.4.3 データ主導プログラミングと加法性

問題 2.73 の c を見てて、あの解では例えば

(+ (+ (** x 2) (* x y)) (** y 2))

みたいな式を deriv に吸わせたら (** y 2) も (* 2 y) になるじゃん、と。おそらくは 問題 2.56 の解が違うのではないか、という事で微分な資料を見てみた。

で、テキストに出ている以下の式
(\frac{d(u^n)}{dx})=nu^{n-1}(\frac{du}{dx})
なんですが、ようやく意味が理解でけた (恥

例えば (** x 2) を微分したら

(* (* 2 (** x 1)) (deriv 'x 'x))

で、(** y 2) を微分したら

(* (* 2 (** y 1)) (deriv 'y 'x))

になる、と。これなら大丈夫だな。

このエントリ(SICP 読み (39) 2.3.2 例: 記号微分)は誤りがある旨を追記しておきます。とほほほほ。

で、修正した解は以下ですか。(修正分の手続きのみ)

(define (install-deriv-package)
 (define (sum l var)
   (define (addend exp) (car exp))
   (define (augend exp) (cadr exp))
   (make-sum (deriv (addend l) var)
             (deriv (augend l) var)))
 (define (product l var)
   (define (multiplier exp) (car exp))
   (define (multiplicand exp) (cadr exp))
   (make-sum
    (make-product (multiplier l) (deriv (multiplicand l) var))
    (make-product (deriv (multiplier l) var) (multiplicand l))))
 (define (exponential l var)
   (define (base x) (car x))
   (define (exponent x) (cadr x))
   (make-product
    (make-product
     (exponent l)
     (make-exponentiation (base l) (- (exponent l) 1)))
    (deriv (base l) var)))

 (put 'deriv '+ sum)
 (put 'deriv '* product)
 (put 'deriv '** exponential)
 'done)

こんな試験も追加。

  ("deriv test (forth)"
   (assert-equal '(+ (* 2 x) y)
		 (deriv '(+ (+ (** x 2) (* x y)) (** y 2)) 'x))
   )

で、d も実装して試してみたのですが、試験に通った。いいのかなぁ。変更点のみ以下に。

(define (deriv exp var)
 (cond ((number? exp) 0)
       ((variable? exp) (if (same-variable? exp var) 1 0))
;       (else ((get 'deriv (operator exp)) (operands exp) var))))
       (else ((get (operator exp) 'deriv) (operands exp) var))))

もうひとつ。

(define (install-deriv-package)
 (define (sum l var)
   (define (addend exp) (car exp))
   (define (augend exp) (cadr exp))
   (make-sum (deriv (addend l) var)
             (deriv (augend l) var)))
 (define (product l var)
   (define (multiplier exp) (car exp))
   (define (multiplicand exp) (cadr exp))
   (make-sum
    (make-product (multiplier l) (deriv (multiplicand l) var))
    (make-product (deriv (multiplier l) var) (multiplicand l))))
 (define (exponential l var)
   (define (base x) (car x))
   (define (exponent x) (cadr x))
   (make-product
    (make-product
     (exponent l)
     (make-exponentiation (base l) (- (exponent l) 1)))
    (deriv (base l) var)))

; (put 'deriv '+ sum)
; (put 'deriv '* product)
; (put 'deriv '** exponential)
 (put '+ 'deriv sum)
 (put '* 'deriv product)
 (put '** 'deriv exponential)
 'done)

最後の問題 2.74 はスルーしたい。(こら