algorithmic differentiation differs from symbolic differentiation as well as numerical. In practice, it takes existing code (i.e., it does not do symbolic math in a new language) and computes the derivative of that function. As you may suspect Lisp is very suitable for AD.
So, I'm trying to implement the code from this paper (Appendix 2):
http://www.cs.berkeley.edu/~fateman/papers/ADIL.pdf
but I get the error "*** - PROGN: variable TWO-ARG has no value". I assume the error is in defarithmetic (and I probably messed up the quotes). Here is the code so far:
Code: Select all
;;; Automatic Differentiation code for Common Lisp
;;; using overloading, forward differentiation.
(defpackage :ga ;generic arithmetic
(:shadow "+" "-" "/" "*" "expt" ;binary arithmetic
"=" "/=" ">" "<" "<=" ">=" ;binary operations
"sin" "cos" "tan" ;... more trigonometric
"atan" "asin" "acos" ;... more inverse trigonometric
"sinh" "cosh" "atanh" ;... more hyperbolic
"expt" "log" "exp" "sqrt" ;... more exponential, powers
"1-" "1+" "abs"
)
(:use :common-lisp)
)
(in-package :ga)
;; structure for f,d: f is function value, and d derivative, default 0
(defstruct (df (:constructor df (f &optional (d 0)))) f d)
;; print df structure with < , >
(defmethod print-object ((a df) stream)(format stream "<~a, ~a>" (df-f a)(df-d a)))
;;function ARITHMETIC-IDENTITY: When fed an operator and a non-nil
;;argument, it returns a value for unary application. What does (+ a) mean?
;;A nil arg means there were NO operands. What does (+ ) mean.
;;It is used only by defarithmetic, which in turn helps
;; us to write out + * - / of arbitrary number of args.
(defmacro arithmetic-identity (op arg)
`(case ,op
(+ (or ,arg 0))
(- (if ,arg (two-arg-* -1 ,arg) 0))
(* (or ,arg 1))
(/ (or ,arg (error "/ given no arguments")))
(expt (or ,arg (error "expt given no arguments")))
(otherwise nil))) ;binary comparisons?
(defun tocl(n) ; get corresponding name in cl-user package
(find-symbol (symbol-name n) :cl-user))
(defmacro defarithmetic (op)
(let ((two-arg
(intern (concatenate 'string "two-arg-" (symbol-name op))
:ga))
(cl-op (tocl op)))
`(progn
(defun ,op (&rest args)
(cond ((null args) (arithmetic-identity `,op nil))
((null (cdr args))(arithmetic-identity `,op (car args)))
(t (reduce (function ,two-arg)
(cdr args)
:initial-value (car args)))))
(defgeneric ,two-arg (arg1 arg2))
(defmethod ,two-arg ((arg1 number) (arg2 number))
(,cl-op arg1 arg2))
(compile `,two-arg)
(compile `,op)
,op)))
(defarithmetic +) ;; defines some of + programs. See below for more
(defarithmetic -)
(defarithmetic *)
(defarithmetic /)
(defarithmetic expt)
Thanks in advance,
Dimitris
PS. I have to admit that I am new to Common Lisp, so I don't know much about macros.