SICPを読む(69) 問題 2.56 記号微分

うっは。微分だよ。ビブン。苦手な分野だとすっかりご無沙汰になってしまう。

2章は数学が無くてステキ!とか思ってたけど、大間違いかもしれない。頑張って乗り越えるぞー。

記号微分について

微分を題材に扱ってるけど、微分はどうでもいい話で、結構重要なポイントが多い。

  • 記号の解析の基礎
    • 記号を分解し、組み立てる。やってることは、インタプリタとあまり変わりない。
  • 最適化の基礎
    • (+ x 0)をxに直す。コレ最適化だと思うよ。読んでよかった。
  • 抽象のレイヤー化
    • これは2章全体の大きなテーマ。体に叩き込もう〜。


それにしても、数式処理ソフトって凄いね。

% maxima
(%i1) expand((x+y)^6);
           6        5       2  4       3  3       4  2      5      6
(%o1)     y  + 6 x y  + 15 x  y  + 20 x  y  + 15 x  y  + 6 x  y + x

宿題が一瞬で解けちまう。学生時代に知ってたらなぁ・・・。


では問題にいこう。

問題 2.56

xのn乗の微分。僕はこんな風に書いてみた。

(define (deriv exp var)
  (cond ((number? exp) 0)
        ((valiable? exp)
         (if (same-valiable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((product? exp)
         (make-sum (make-product (multiplier exp)
                                 (deriv (multiplicand exp) var))
                   (make-product (deriv (multiplier exp) var)
                                 (multiplicand exp))))
        ((exponentiation? exp)
         (if (same-valiable? (base exp) var)
             (make-product (exponent exp)
                           (make-exponentiation (base exp)
                                                (make-sum (exponent exp) -1)))
             0))
        (else (error "unknown expression type"))))

回答見たら

回答を見たら、make-productが一回多い!!

僕の場合、xについての微分をするときyの2乗があったら、0にしてた。でも、それ以上の条件があるかもしれない(具体例が思い浮かばないのが数学の弱さ)

もう一回、make-productしちまえば完璧!(** y 2)が綺麗さっぱり消えます。セクシーっす。

テストツールを試す

Gaucheのテストツール+ひげぽんマクロ使ってみた。なかなかいい感じかも。

<exponentiation>---------------------------------------------------------------
test (exponentiation? '(** x 2)), expects #t ==> ok
test (base '(** x 2)), expects x ==> ok
test (exponent '(** x 2)), expects 2 ==> ok
test (make-exponentiation 'x 2), expects (** x 2) ==> ok
test (make-exponentiation 'x 0), expects 1 ==> ok
test (make-exponentiation 'x 1), expects x ==> ok
test (make-exponentiation '2 2), expects 4 ==> ok
test (deriv '(** x 2) 'x), expects (* 2 x) ==> ok
test (deriv '(** x y) 'x), expects (* y (** x (+ y -1))) ==> ok
test (deriv '(** 2 2) 'x), expects 0 ==> ok
test (deriv '(** y y) 'x), expects 0 ==> ok
passed.

ツールは活躍するが、具体例が全然出てこない。数学も修行しなくては・・・