I actually have alpha conversion supported:
(define-symbolic-function f1 (x y) (+ (* x x) y)) F1
(define-symbolic-function f2 (y x) (+ (* y y) x)) F2
(alpha-convert #'f1 'z 'x) #<(Z Y) -> (+ (* Z Z) Y)>
(alpha-convert #'f1 'x 'y) #<(Z X) -> (+ (* Z Z) X)>
(alpha-convert #'f1 'y 'z) #<(Y X) -> (+ (* Y Y) X)>
#'f1 #<(Y X) -> (+ (* Y Y) X)>
#'f2 #<(Y X) -> (+ (* Y Y) X)>
Defining a crude partial differentiator wouldn't be tough. In fact, I just modified DIFFERENTIATE to take an optional (zero-based) index parameter:
#'f1 #<(Y X) -> (+ (* Y Y) X)>
(differentiate #'f1 0) #<(Y X) -> (+ (+ (* 1 Y) (* Y 1)) 0)>
(differentiate #'f1 1) #<(Y X) -> (+ (+ (* 0 Y) (* Y 0)) 1)>
Cheers, Robert On Tue, Sep 11, 2012 at 12:18 PM, Andy Latto <andy.latto@pobox.com> wrote:
On Tue, Sep 11, 2012 at 1:03 PM, Fred lunnon <fred.lunnon@gmail.com> wrote:
<< Also notice that DIFFERENTIATE never required any "variable" parameter. Since differentiation occurs on *functions* and not *expressions*, we know what we are differentiating with respect to. (This is in my opinion the right way to differentiate.) >>
So how are you going to deal with differentiating a function of several variables? WFL
with a function partial-derivative, that takes as arguments a function of n variables and a *number* not a variable name, giving the position of the argument with respect to which you differentiate it.
(define-symbolic-function f1 (x y) (+ (*x x) y))
and
(define-symbolic-function f2 (y x) (+ (* y y) x))
define the same function. So you don't want a function like
(badly-defined-partial-derivative f1 'x)
which returns a different function than
(badly-defined-partial-derivative f2 'x)
You want a function where
(partial-derivative f1 1)
returns the same function as
(partial-derivative f2 1)
I use "same function" here to mean "will return the same values given the same arguments", not "actually the same object". But since symbolic functions are immutable objects, this is functionally equivalent.
Andy
On 9/11/12, quad <quadricode@gmail.com> wrote:
Hey all:
I thought I might share a little thing I've been hacking on called "symbolic functions", since Henry Baker recently told math-fun about chebfun (IIRC).
First, define a pythag/distance function because we'll need it later:
(defun pythag (x y) (sqrt (+ (* x x) (* y y))))
PYTHAG
Now we define a symbolic function UNIT-SINE:
(define-symbolic-function unit-sine (x) (sin (* (* 2 pi) x)))
UNIT-SINE
Of course this is thew sine function with a period of 1. We can evaluate it as normal:
(unit-sine 1.0)
-2.4492935982947064d-16 ;; approximately 0.0
It can be used in every way a traditional Lisp function can be used. Mapped, reduced, composed, disposed, etc. But it has a special property. We can do cool operations with it. For example, we can differentiate it:
(pythag (unit-sine 0.75) (funcall (differentiate #'unit-sine) 0.75))
1.0d0
which is to be expected from sin^2 + cos^2 = 1. But of course, maybe I'm just using the difference quotient. But:
(loop :for i :from 0.0 :to 1.0 :by 0.1 :collect (- (* 2 pi (cos (* 2 pi i))) (funcall (differentiate #'unit-sine) i)))
(0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0 0.0d0)
Surely with something like the difference quotient, we'd get some numerical error.
Of course, there's a trick, and it's what I call "symbolic functions". They're likely not a new idea at all, but I've never seen them like this.
A symbolic function is a regular ol' executable function equipped with its symbolic form under the hood. It has the appearance of a regular function and can be used in every way a regular function can be used, so it's a transparent thing. But evaluating one by itself exposes the information:
#'unit-sine
#<X -> (SIN (* (* 2 PI) X))>
Like I said, this is a regular, *COMPILED* function. When you provide a value for X, it is not re-interpreted to get a numerical value. It's calling the compiled form of that. However, numerical evaluation isn't the interesting thing. We can also produce new kinds of function using SLAMBDA (Symbolic LAMBDA):
(slambda (x) (* x x))
#<X -> (* X X)>
which work exactly like LAMBDA functions. What happens if we differentiate?
(differentiate (slambda (x) (* x x)))
#<X -> (+ (* 1 X) (* X 1))>
We get a brand new SLAMBDA, recompiled on-the-fly (so a poor man's JIT!). DIFFERENTIATE is really just a classical (and very naive) symbolic differentiator:
https://bitbucket.org/tarballs_are_good/symbolic-function/raw/fa394a19d24e/d...
Also notice that DIFFERENTIATE never required any "variable" parameter. Since differentiation occurs on *functions* and not *expressions*, we know what we are differentiating with respect to. (This is in my opinion the right way to differentiate.)
What does differentiating UNIT-SINE produce?
(differentiate #'unit-sine) #<X -> (* (+ (* (+ (* 0 PI) (* 2 0)) X) (* (* 2 PI) 1)) (COS (* (* 2 PI) X)))>
Of course, that's very ugly, but when compiled, that ugliness gets washed away through constant folding and friends. However (!), it would not be difficult to write a simple symbolic simplifier for symbolic functions either.
Anyway, the code is here:
Main Meat: https://bitbucket.org/tarballs_are_good/symbolic-function/raw/fa394a19d24e/s...
Repository: https://bitbucket.org/tarballs_are_good/symbolic-function
There are some outstanding "problems" really. For example, it's not immediately clear to me how to symbolically manipulate constructs like LET and friends in a mathematical fashion, or deal with symbolic functions that stray away from "symbolicness" (like functions which use mutation, etc.)
But I think the biggest advantage is that you get truly fast numerical code which is transparently done with symbolic operations, sort of like chebfun (except chebfun is more numeric than symbolic: it just has function approximations).
If you're interested in running the code, you need a dependency (the metaobject protocol), and you need to know how to use ASDF (or Quicklisp). (I'd be more than happy to describe those steps.)
Any comments, history, suggestions, fan fiction, love letters, death threats?
Cheers,
Robert Smith
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun
-- Andy.Latto@pobox.com
_______________________________________________ math-fun mailing list math-fun@mailman.xmission.com http://mailman.xmission.com/cgi-bin/mailman/listinfo/math-fun