3

リスト形式で表される式の単純な導関数を計算する小さなプログラムを作成しています。つまり2x^2、として表され(* 2 (exp x 2))、次の関数を定義しています。

;; derivative of a constant is 0
(define (diff-constant x E) 0)

;; computes derivative of E with respect to x where E can only be of the form
;; (+ x x ...)
(define (diff-sum x E)
  (cond ((or (not (list? E)) (null? E)) 0)
        ((eq? (car E) x) (+ 1 (diff-sum x (cdr E))))
        (else (diff-sum x (cdr E)))))

;; computes derivative of E with respect to x where E can only be of the form
;; (* x y)
(define (diff-product x E)
  (cond ((and (eq? x (cadr E)) (eq? x (caddr E))) (list '* 2 x))
        ((eq? x (cadr E)) (list (caddr E)))
        ((eq? x (caddr E)) (list (cadr E)))
        (else 0)))

;; computes derivative of E with respect to x where E can only be of the form
;; (expt x y) which is x^y
(define (diff-expt x E)
  (cond ( not (eq? x (cadr E)) 0)
        ((eq? 1 (caddr E)) 0)
        ((eq? 2 (caddr E)) (cadr E))
        (else (list '* (caddr E) (list 'expt x (- (caddr E) 1))))))

次のように定義されたディスパッチテーブルもあります。

;; Dispatch Table of supported operators.
 (define diff-dispatch
   (list (list '+ diff-sum)
         (list '* diff-product)
         (list 'expt diff-expt)
         ))

diffそして、方程式E(リスト形式)を取り、ディスパッチテーブルを使用して導関数を計算しx、結果を返す事前定義された関数を呼び出す関数を作成しようとしています

ここに私がこれまでに持っているものがありますが、残りはわかりません

;; Differentiate expression E with respect to x.
(define (diff x E)
  (cond ((number? E) (diff-constant x E))
        ;; insert code here to handle the other base case - variables
        ...
        (else    ; insert code here to lookup the appropriate function in the
                 ; dispatch table based on the operator in the expression,
                 ; then call that function to differentiate the expression
                     (diff-func x E))))))

例: (つまり、1 + x + x)(diff 'x '(+ x (* x x)))と評価される必要があります。(+ 1 (+ (* 1 (* x)) (* x 1)))

4

2 に答える 2

2

オスカー・ロペスの答えに付け加えると、プロレベルのラケットプログラムでは、ディスパッチをできるだけ早くしたいと考えています。テストする項目の数が数項目を超えて増加する場合は、ベクトルやハッシュ テーブルなどの高速検索をサポートするデータ構造を使用する必要があります。データ表現は重要な場合があります。リストは、知っておくべき最良のデータ構造でも、唯一のデータ構造でもありません。すべてに連結リスト表現を使用するという SICP の偏見は称賛に値します。しかし、連結リストが適切な構造でない場合もあります。

ハッシュ テーブル ベースのアプローチでは、ディスパッチ テーブルの設定は非常に似ています。

;; in professional-level Racket (#lang racket)
(define dispatch-table (hash '+ diff-sum
                             '* diff-product
                             ;; ... etc
                             ))

テーブルへのルックアップは、ハッシュ参照から離れています。

(define op '+)
(hash-ref dispatch-table op)      ;;; => diff-sum
于 2012-10-18T17:40:23.103 に答える
2

SICPの本には、記号微分を実行するためのSchemeプログラムを構築する方法を詳細に説明するセクション全体があります.セクション§2.3を見てください。特に、1 つのケースを見逃していることに注意してください。派生する式が変数の場合はどうなるでしょうか。リンクをチェックして、正しい軌道に乗っていることを確認してください。

ここで、質問に答えます。コードで使用されるテーブル表現が与えられれば、ディスパッチャを実装するのは簡単です。これらの線に沿ったものは、正しい微分手順を適用するために機能します。

((cadr             ; obtain the differentiation procedure
  (assoc           ; look for the differentiation procedure
   (car E)         ; obtain the operator in the expression
   diff-dispatch)) ; dispatch table
 x E)              ; apply the procedure with parameters `x` and `E`

適用する正しい手順を見つけるための「トリック」は、テーブルが連想リストとして実装されているという事実にあり、assoc手順はそのようなリスト内のデータを見つけるために正確に設計されていることに注意してください。詳細については、ドキュメントを参照してください。

于 2012-10-17T23:32:43.197 に答える