yacas icon indicating copy to clipboard operation
yacas copied to clipboard

Function application seem to evaluate before application.

Open Isomorph70 opened this issue 4 years ago • 13 comments

Following test show the problem. D({x,y} will be applied to node instead of 9*x^8.

Verify(MapSingle({{node},D({x,y}) node},{9x^8,0}),{D({x,y}) 9x^8,D({x,y}) 0});

Verify(MapSingle(Lambda({{node},D({x,y}) node}),{9x^8,0}),{D({x,y}) 9x^8,D({x,y}) 0});

Isomorph70 avatar Jul 17 '20 13:07 Isomorph70

Ops, an error in coping the examples. The correct ones is.

Verify(MapSingle({{node},D({x,y}) node},{9*x^8,0}),{D({x,y}) 9*x^8,D({x,y}) 0});

Verify(MapSingle(Lambda({{node},D({x,y}) node}),{9*x^8,0}),{D({x,y}) 9*x^8,D({x,y}) 0});

Isomorph70 avatar Jul 18 '20 10:07 Isomorph70

Seem like githubs text rendering remove multiplication signs.

Isomorph70 avatar Jul 18 '20 10:07 Isomorph70

Hi,

I agree that this is a bit disappointing result. But it is actually for a reason, even though not a very important one. The D() operator is a macro, so it's application is a bit more convoluted. Fortunately, it's built around much simpler Deriv() operator, which in your case can be used like

In> MapSingle(Lambda({node},{Deriv(x) node, Deriv(y) node}),{9*x^8,0})
Out> {{72*x^7,0},{0,0}}

It this what you're actually after? Does the workaround lokk acceptable?

Cheers, Grzesiek

grzegorzmazur avatar Jul 21 '20 12:07 grzegorzmazur

I am basically trying to make a rule that take in a list of variables vl with n elements and a list of expressions el with m elements and then derive on each expression. Like {{Deriv(vl[1]) el[1],,,Derive(vl[n]) el[1]},.........,{Deriv(vl[1]) el[m],...,Deriv(vl[n]) el[m]}}.

Isomorph70 avatar Jul 21 '20 14:07 Isomorph70

OK, then how about

derivs(vars_IsList, exprs_IsList) <--
    MapSingle(Lambda({e}, MapSingle(Lambda({v}, Deriv(v) e), vars)), exprs);

Would this work for you?

grzegorzmazur avatar Jul 21 '20 20:07 grzegorzmazur

Alternatively, risking the wrath of functional programming Gods

derivs(vars_IsList, exprs_IsList) <-- [
    Local(e, v, row, result);
    result := {};
    ForEach(e, exprs) [
        row := {};
        ForEach(v, vars)
	    DestructiveAppend(row, Deriv(v) e);
	DestructiveAppend(result, row);
    ];
    result;
];

grzegorzmazur avatar Jul 21 '20 20:07 grzegorzmazur

Something more like this will be optimal. 10 # derivs(vars_IsList, _expr)_(Not IsList(expr)) <-- MapSingle(Lambda({v}, Deriv(v) expr), vars); 20 # derivs(vars_IsList, exprs_IsList) <-- MapSingle(Lambda({e}, derivs(vars,e)), exprs);

Isomorph70 avatar Jul 21 '20 21:07 Isomorph70

Or in full functional mode. 10 # derivs(_vars, exprs_IsList) <-- If(Length(exprs)=0,{},derivs(vars,Head(exprs)):derivs(vars,Tail(exprs))); 20 # derivs(vars_IsList, _expr) <-- If(Length(vars)=0,{},(derivs(Head(vars),expr)):derivs(Tail(vars),expr)); 30 # derivs(_var,_expr) <-- Deriv(var) expr;

Isomorph70 avatar Jul 22 '20 00:07 Isomorph70

Also, I have been working on a multidimensional Taylor expansion, that I can contribute to the project.

Isomorph70 avatar Jul 22 '20 00:07 Isomorph70

That's awesome, thanks! :)

And obviously the code you suggest is better then mine. The only possible improvement I can see is providing additional rules instead of using If(), like

5 # derivs(_vars, {}) <-- {};
10 # derivs(_vars, exprs_IsList) <-- derivs(vars,Head(exprs)):derivs(vars,Tail(exprs));
15 # derivs({}, _expr) <-- {};
20 # derivs(vars_IsList, _expr) <-- derivs(Head(vars),expr):derivs(Tail(vars),expr);
30 # derivs(_var,_expr) <-- Deriv(var) expr;

but I admit that it's a minor change and based more on personal preference than anything else.

Cheers, Grzesiek

grzegorzmazur avatar Jul 22 '20 09:07 grzegorzmazur

Perfect... Here are some tests, that our new derivs can do, but D can't.

Verify([Local(vl);vl :={x,y};derivs(vl, x+c);],derivs({x,y}, x+c)); Verify(MapSingle(Lambda({node},derivs({x,y},node)),{9*x^8,0}),{derivs({x,y}, 9*x^8),derivs({x,y},0)});

Verify([Local(vl);vl :={x,y};D(vl) x+c;],D({x,y}) x+c); Verify(MapSingle(Lambda({node},D({x,y}) node),{9*x^8,0}),{D({x,y}) 9*x^8,D({x,y}) 0});

Isomorph70 avatar Jul 22 '20 20:07 Isomorph70

The basic issue with D() is that it has shady semantics, definitely to complex for its own good. It's easy to use for some basic operations, but for anything more involved it fails miserably. If ever, it should be used only by an end user to do something simple ad hoc. Definitely it has no place in any implementation of other mechanisms.

On the other hand the semantics you suggest for what is now called derivs() looks good. I think it'd be reasonable to incorporate it into Derivs(), which till now has only basic capabilities, but does them reasonably well.

What do you think about it?

grzegorzmazur avatar Jul 23 '20 13:07 grzegorzmazur

Yes, We better integrate it into Deriv(), so everyone can use it.

Isomorph70 avatar Jul 24 '20 23:07 Isomorph70