[lisplab-cvs] r80 - src/core
Jørn Inge Vestgården
jivestgarden at common-lisp.net
Mon Aug 10 18:57:50 UTC 2009
Author: jivestgarden
Date: Mon Aug 10 14:57:49 2009
New Revision: 80
Log:
some testing on symbolic stuff
Modified:
src/core/level0-expression.lisp
Modified: src/core/level0-expression.lisp
==============================================================================
--- src/core/level0-expression.lisp (original)
+++ src/core/level0-expression.lisp Mon Aug 10 14:57:49 2009
@@ -25,6 +25,9 @@
(defun expr (&rest args)
(make-instance 'expression :list args))
+(defun make-expression (args)
+ (make-instance 'expression :list args))
+
(defmethod print-object ((ex expression) stream)
(prin1 (expression-list ex) stream))
@@ -102,12 +105,19 @@
;;;; Then the derivatives
(defmethod .= ((x symbol) (y symbol) &optional whatever)
+ (declare (ignore whatever))
(eql x y))
(defmethod .log ((x symbol) &optional (n nil))
(if x
- (expr '.log x n)
- (expr '.log x)))
+ (make-expression `(.log ,x ,n))
+ (make-expression `(.log ,x))))
+
+(defmethod .sin ((x symbol))
+ (make-expression `(.sin ,x)))
+
+(defmethod .cos ((x symbol))
+ (make-expression `(.cos ,x)))
(defgeneric .partial (epxr var)
(:documentation "Parial derivative of the expressions with regards to the variable."))
@@ -117,20 +127,151 @@
1
0))
-(defmethod .partial ((x expression) (y symbol)))
+(defmethod .partial ((x number) (y symbol))
+ 0)
+
+(defmethod .partial ((x expression) (var symbol))
+ ;; The best would'we been to have no special treatment of .+ and .*,
+ ;; and just go through the partial-of-function.
+ (let ((expr (expression-list x)))
+ (if (atom expr)
+ (.partial expr var)
+ (case (car expr)
+ (.+ (apply #'.+ (mapcar (lambda (expr)
+ (.partial (make-expression expr) var))
+ (cdr expr))))
+ (.* 'todo)
+ (t (let* ((args-val (cdr expr))
+ (args-sym (mapcar (lambda (x) (gensym)) args-val))
+ (pos (position var args-val)))
+ (if pos
+ (.partial-of-function (car expr) pos args-val) ; argument is a symbol
+ (.* (make-expression
+ (sublis (mapcar #'cons args-sym args-val)
+ (expression-list
+ (.partial-of-function (car expr) 0 args-sym))))
+ (.partial (make-expression (car args-val)) ; Todo make sum
+ var)))))))))
+
+
+
+;;; Now test the idea of symbolic functions
+
+(defclass symbolic-function ()
+ ((args :initarg :args :initform '(x y) :accessor symbolic-function-args)
+ (body :initarg :body :initform '(* x y) :accessor symbolic-function-body))
+ (:metaclass sb-mop:funcallable-standard-class))
+
+(defmethod initialize-instance :after ((sf symbolic-function) &key)
+ (with-slots (args body)
+ sf
+ (sb-mop:set-funcallable-instance-function
+ sf
+ (let* ((args2 args)
+ (body2 body)
+ (code `(lambda ,args2 ,body2))
+ (fun (eval code)))
+ fun))))
+
+(defun make-symbolic-function (args body)
+ (make-instance 'symbolic-function :args args :body body))
+
+(defmacro .fun (args &body body)
+ `(make-symbolic-function ',args ', at body))
+
+
+(defmethod print-object ((o symbolic-function) stream)
+ (format stream "(.fun ~a ~a)"
+ (symbolic-function-args o)
+ (symbolic-function-body o)))
+
+(defun change-argument-names (sf args)
+ "Makes an identical symbolic function, but with new argument names."
+ (let* ((alst (mapcar #'cons (symbolic-function-args sf) args))
+ (new-body (sublis alst (symbolic-function-body sf))))
+ (make-symbolic-function args new-body)))
(defgeneric .partial-of-function (fun arg-num args)
- (:documentation "The parial derivive of a function"))
+ (:documentation "The parial derivive of a function. Retuns a list."))
(defmethod .partial-of-function ((f (eql '.log)) (arg-num (eql 0)) args)
- "Args must be a list"
+ ;; Args must be a list
(if (cdr args)
- (expr './ 1 (car args) (.log (cadr args)))
- (expr './ (car args))))
+ (./ 1 (car args) (.log (cadr args)))
+ (./ (car args))))
(defmethod .partial-of-function ((f (eql '.sin)) (arg-num (eql 0)) args)
- (expr '.cos (car args)))
+ (.cos (car args)))
(defmethod .partial-of-function ((f (eql '.cos)) (arg-num (eql 0)) args)
- (expr '.- (expr '.sin (car args))))
+ (.- (.sin (car args))))
+
+
+
+
+;;;; Some simplifications
+(defmethod .add ((a symbolic-function) (b symbolic-function))
+ (if (equal (symbolic-function-args a)
+ (symbolic-function-args b))
+ (make-symbolic-function
+ (symbolic-function-args a)
+ (append '(.+) (symbolic-function-body a) (symbolic-function-body b)))
+ `(.+ ,a ,b)))
+
+
+(defmethod .mul ((a symbolic-function) (b symbolic-function))
+ (if (equal (symbolic-function-args a)
+ (symbolic-function-args b))
+ (make-symbolic-function
+ (symbolic-function-args a)
+ (append '(.+) (symbolic-function-body a) (symbolic-function-body b)))
+ `(.* ,a ,b)))
+
+
+
+;;; Some simple simlifications
+
+(defmethod .add :around ((a symbol) (b number))
+ (if (eql b 0)
+ a
+ (call-next-method)))
+
+(defmethod .add :around ((b number) (a symbol))
+ (if (eql b 0)
+ a
+ (call-next-method)))
+
+(defmethod .add :around ((a expression) (b number))
+ (if (eql b 0)
+ a
+ (call-next-method)))
+
+(defmethod .add :around ((b number) (a expression))
+ (if (eql b 0)
+ a
+ (call-next-method)))
+
+(defmethod .mul :around ((a symbol) (b number))
+ (case b
+ (0 0)
+ (1 a)
+ (t (call-next-method))))
+
+(defmethod .mul :around ((b number) (a symbol))
+ (case b
+ (0 0)
+ (1 a)
+ (t (call-next-method))))
+
+(defmethod .mul :around ((a expression) (b number))
+ (case b
+ (0 0)
+ (1 a)
+ (t (call-next-method))))
+
+(defmethod .mul :around ((b number) (a expression))
+ (case b
+ (0 0)
+ (1 a)
+ (t (call-next-method))))
\ No newline at end of file
More information about the lisplab-cvs
mailing list