> PS: Surprisingly, further abstraction of the chain rule does not work.
> With
>
> Deriv x (f y) = (Deriv y (f y)) * (Deriv x y) ;
"f" is in head position here, and is assumed to be literal.
--
Note that nobody these days would clamor for fundamental laws John Cowan
of *the theory of kangaroos*, showing why pseudo-kangaroos are co...@ccil.org
physically, logically, metaphysically impossible. http://www.ccil.org/~cowan
Kangaroos are wonderful, but not *that* wonderful. --Dan Dennett on zombies
Maybe that failed because the constants were actually ints? :) There's a
generic number type which can be used to match anything that looks like
a number. (Pure has most of the usual numeric tower, see here for a list
of numeric types defined by the prelude:
http://docs.pure-lang.googlecode.com/hg/purelib.html#prelude-types.)
> 2) My rules 11-18 are humbug, of course; they work in simplifying the
> resulting expressions for the special examples I stated above, but
> fail to simplify more complicated expressions. Is there a systematic
> way for simplifying?
Simplifying arithmetic expressions can be surprisingly complex. It
depends on which kind of normal form you actually want to have. If terms
should be in sum of products form, you'll probably want to do some kind
of lexicographic sorting so that you end up with something like
c1*x11*...*x1n + c2*x21*...*x2m where the ci are constants and each
variable tuple (xi1,...,xin) only occurs once. This cannot be done
efficiently with simple toplevel rules for associativity, commutativity
and distributivity alone. You'll probably need to work with local rule
sets to get that kind of thing to work. See
http://docs.pure-lang.googlecode.com/hg/purelib.html#reduce.
Albert
--
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email: Dr.G...@t-online.de, a...@muwiinfa.geschichte.uni-mainz.de
WWW: http://www.musikinformatik.uni-mainz.de/ag
I should maybe point out that the right way to write this rule is:
Deriv x (f@_ y) = (Deriv y (f y)) * (Deriv x y) ;
See
http://docs.pure-lang.googlecode.com/hg/pure.html#head-function-pitfalls.
I haven't really reviewed your code in detail, but I suspect that the
above rule loops on 'Derive u (v w)', so you're getting a stack
overflow. You'll have to do more checking on the y argument to ensure
that the chain rule is really applicable.
Also, you might want to check
http://docs.pure-lang.googlecode.com/hg/pure.html#stack-size-and-tail-recursion
to see how you can set the PURE_STACK environment variable to get
orderly exceptions in case of a stack overflow. And then you might want
to read up on how to run your script with the symbolic debugger to see
where it goes wrong. ;-)
> diff id = cnst 1;
> diff sin = cos;
Pure distinguishes between functions/constructors (same thing) and
variables by whether they appear in the head of the expression or not.
So what you have written is the exact equivalent of:
diff x = cnst 1;
diff x = cos;
You can see why the second rule can never be reached.
The only way to manage a point-free style in Pure is to declare 'sin'
as a nonfix operator. But overall I think it is better to write "diff
sin x = cos x" and "diff x::number = 1".
When you try to write language A in the style of language B, you often
have problems like these. Just as with human languages, it is necessary
to learn to think in the second language to use it fluently.
--
John Cowan http://www.ccil.org/~cowan co...@ccil.org
"After all, would you consider a man without honor wealthy, even if his
Dinar laid end to end would reach from here to the Temple of Toplat?"
"No, I wouldn't", the beggar replied. "Why is that?" the Master asked.
"A Dinar doesn't go very far these days, Master. --Kehlog Albran
Besides, the Temple of Toplat is across the street." The Profit
As John already pointed out, 'id' and 'sin' are interpreted as variables
there, as they are not the head of an application. You can fix that by
declaring them as "nonfix" symbols:
nonfix id sin;
But note that this changes the lexical meaning of those symbols so that
they are *always* interpreted as literals. To avoid that, you can either
use an explicit comparison:
diff f = cnst 1 if f === id;
= cos if f === sin;
Or you can "escape" the symbol by using a namespace qualifier:
diff ::id = cnst 1;
diff ::sin = cos;
See http://docs.pure-lang.googlecode.com/hg/pure.html#as-patterns (have
a look at the second part of that section which begins with "Sometimes
you may also run into the complementary problem, i.e., to match a
function argument against a given function.").
BTW, you may want to use cst instead of cnst. cst is defined in the
prelude as cst x y = x. See
http://docs.pure-lang.googlecode.com/hg/purelib.html#basic-combinators
Hey, this trick is really neat, I wouldn't have thought of that! :) The
only problem is that the '+' on the rhs of the local definition is not
the same '+' as on the lhs. (Well, it's the same symbol, but it's bound
to the local '+' function there.) But that's easy to fix, you just need
to invoke the global '+' in the body of the local function:
f + g = f + g with (f+g) x = f x ::+ g x end;
NB: I'm not sure whether you need this here, but it might also be a good
idea to check that f and g are actually function objects which accept an
argument:
f + g = f + g with (f+g) x = f x ::+ g x end if nargs f > 0 && nargs g > 0;
If you do the same for the other operators, the rules will work just fine:
> (diff $ id + id) 1;
2
> (diff $ id + id*sin) 1;
2.38177329067604
> By now I couldn't utilize + and * as
>
> f + g = \x -> f x + g x;
> f * g = \x -> f x * g x;
No, this won't work because a lambda produces an anonymous function, and
there's no way you could match that in 'diff'.
> I still have a vague perception of the place of lambdas in term rewriting.
Well, lambdas don't exist in standard (first-order) term rewriting, they
are a Pure extension. And an evaluated lambda term can't be rewritten in
Pure, because it's just an atomic object (basically a function pointer)
as far as the rewriting machinery is concerned.
Pure only allows you to rewrite a lambda term while it's still
unevaluated, i.e., at macro expansion time. You might thus employ some
macro rules to wrap up the lambda in a way that would allow 'diff' to
dissect it, but that would make things much more complicated. I think
that your trick with the local '+' function is much nicer!
Not quite. As you already found out, f evaluates to an anonymous
function in the latter case. Both will yield the same results on all
arguments, though.
-x is a synonym for neg x, so you're actually defining a local neg
function there. Use ::neg on the rhs of the local definition and it will
work.
You'll need reflection to deal with such cases. There are ways to
determine the rewriting rules defining a function:
> f2 x = sin(cos x) + x;
> get_fundef f2;
[f2 x-->sin (cos x)+x]
See http://docs.pure-lang.googlecode.com/hg/pure.html#reflection
At least in simple cases that would allow you to derive a point-free
form to which diff would be directly applicable. Of course in the
general case, if f2 is completely arbitrary, a closed-form differential
may not even exist.
But, the point-free style also breaks down with more than one
argument, whereas with explicit arguments, you can trivially
generalize to partial derivatives.
Mike
> --
> You received this message because you are subscribed to the Google Groups "pure-lang" group.
> To post to this group, send email to pure...@googlegroups.com.
> To unsubscribe from this group, send email to pure-lang+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/pure-lang?hl=en.
>