Our first step will be creating a new dual-number data type to perform"forward-mode” automatic differentiation. For dual-numbers in Scheme, an implementation using pairs makes sense. The first element of the pair will be x and the second will be the infinitesimal x′:(x . x').
Building upon the program in 2.3.2: Symbolic Differentiation from SICP and our dual numbers, create a function deval to allow more declarative evaluation of derivative expressions.
deval: (expression x symbol x value) → dual-number
A Dual-Number Type
(define (make-dual n d) (cons n d))
(define (val x) (car x))
(define (dval x) (cdr x))
(define (make-variable x) (make-dual x 1))
(define (add-dual u v)
(make-dual (+ (val u) (val v))
(+ (dval u) (dval v))))
(define x (make-variable 2))
(add-dual x x) --> (4 . 2)
Warmup
Dual Number Arithmetic
(quo-dual (make-constant 1)
(cos-dual (pow-dual (sin-dual x) (make-constant 2))))
-->(1.48 . -1.21)
A Derivative Interpreter
(deval '(* x 2) 'x 2) --> (4 . 2)
(deval '(/ 1 (cos (^ (sin x) 2))) 'x 2) --> (1.48 . -1.21)
(Optional) Next Steps