2013年6月15日土曜日

開発環境

計算機プログラムの構造と解釈(Gerald Jay Sussman(原著)、Julie Sussman(原著)、Harold Abelson(原著)、和田 英一(翻訳)、ピアソンエデュケーション、原書: Structure and Interpretation of Computer Programs (MIT Electrical Engineering and Computer Science)(SICP))の2(データによる抽象の構築)、2.4(抽象データの多重表現)、2.4.3(データ主導プログラミングと加法性)の問題 2.73を解いてみる。

その他参考書籍

問題 2.73

a.

やったことは、演算(derive)対型(+, *)というテーブルを使用したデータ主導プログラミングにしていて、テーブルから対応する手続きを取得し実行している。

+*
derivderiv-sumderiv-product

述語number?やvariable?がデータ主導の振り分けに吸収できないのは、数値や変数がリストではないので、手続きoperatorやoperandsを適用できないから。

b, c.

コード

sample.scm

;; 和の微分
(define (install-sum-package)
  ;; 内部手続き
  (define (inner-deriv exp var)
    (make-sum (deriv (addend exp) var)
              (deriv (augend exp) var)))
  (define (addend exp) (cadr exp))
  (define (augend exp) (caddr exp))
  (define (make-sum a1 a2)
    (cond ((=number? a1 0) a2)
          ((=number? a2 0) a1)
          ((and (number? a1) (number? a2)) (+ a1 a2))
          (else (list '+ a1 a2))))
  (define (=number? exp num)
    (and (number? exp) (= exp num)))
    
  ;; システムの他の部分とのインターフェース
  (put 'deriv '+ inner-deriv)
  'done)

;; 積の微分
(define (install-product-package)
  ;; 内部手続き
  (define (inner-deriv exp var)
    (make-sum
      (make-product (multiplier exp)
                    (deriv (multiplicand exp) var))
      (make-product (deriv (multiplier exp) var)
                    (multiplicand exp))))
  (define (multiplier exp) (car (operands exp)))
  (define (multiplicand exp) (cadr (operands exp)))
  (define (make-product m1 m2)
    (cond ((or (=number? m1 0) (=number? v2 0)) 0)
          ((=number? m1 1) m2)
          ((=number? m2 1) m1)
          ((and (number? m1) (number? m2)) (* m1 m2))
          (else (list '* m1 m2))))
  (define (=number? exp num)
    (and (number? exp) (= exp num)))

  ;; システムの他の部分とのインターフェース
  (put 'deriv '* inner-deriv)
  'done)

;; べき乗の微分
(define (install-expt-pakcage)
  ;; 内部手続き
  (define (inner-deriv exp var)
    (let ((n (exponent exp))
          (u (base exp)))
      (* n
         (make-exponentitation u (- n 1))
         (deriv u var))))
  (define (base x) (cadr x))
  (define (exponent x) (caddr x))
  (define (make-exponentiaton a b)
    (cond ((=number? b 0) 1)
          ((=number? b 1) a)
          ((and (number? a) (number? b)) (expt a b))
          (else (list '** a b))))
  (define (=number? exp num)
    (and (number? exp) (= exp num)))

  ;; システムの他の部分とのインターフェース
  (put 'deriv '** inner-deriv)
  'done)

d.

各微分のパッケージの表を操作する手続きputの第1引数、第2引数の順序を入れ替える、つまり、次のように変更すればいい。

コード

sample.scm

;; 式の型を、結合している代数演算ではなく、derivにした場合の微分システム

;; 和の微分
(define (install-sum-package)
 ;; 内部手続きは同じなので省略
  ;; システムの他の部分とのインターフェース
  (put '+ 'deriv inner-deriv)
  'done)

;; 積の微分
(define (install-product-package)
 ;; 内部手続きは同じなので省略
  ;; システムの他の部分とのインターフェース
  (put '* 'deriv inner-deriv)
  'done)

;; べき乗の微分
(define (install-expt-pakcage)
 ;; 内部手続きは同じなので省略
  ;; システムの他の部分とのインターフェース
  (put '** 'deriv inner-deriv)
  'done)

パッケージを呼び出して出来上がるテーブル。

deriv
+deriv-sum
*deriv-product
**deriv-expt

0 コメント:

コメントを投稿