1
$\begingroup$

The problem starts with a medium-complicated function, f[y0_,y1_,y2_,s_,d_], with everything Real. The innards of this function don’t matter here, except to say that it is analytically differentiable.

A numerical calculation needs repeated calculation of the partial derivative of this wrt various combinations of the first three parameters, for various values of the five parameters.

This can be done as follows.

D[ f[y0,y1,y2,s,d], {y0,2}, {y1,1}, {y2,1} ] //FullSimplify  

Then copy-paste the answer into

f0012[y0_,y1_,y2_,s_,d_] = ….

Yuck. The copy-paste feels like an error in the making. So what’s wanted might be a semi-delayed set: doing the analytical stuff immediately, but preserving the separate scope of the parameters. Or something else.

Please, kind experts of mathematica.stackexchange.com, how would you recommend doing this?

Further details requested.

f[y0_,y1_,y2_,s_,d_] := Log[ Theta[y0,y1,y2,s,d] / constant ] * 
  Theta[y0,y1,y2,s,d] / D[Theta[y0,y1,y2,s,d], y0]  

where Theta is itself a complicated and completely differentiable thing. Assume, falsely but not unhelpfully, that Theta is the sum of (Exp[-#] (#+1)^10) over the parameters.

$\endgroup$
6
  • 1
    $\begingroup$ Please include a (working) dummy definition for f. Otherwise we have to make one before attempting to answer the question. Make your question easy to answer. $\endgroup$
    – Mr.Wizard
    Feb 13, 2015 at 22:25
  • 1
    $\begingroup$ You are correct that copy-paste is a bad idea. Instead, give the derivative a name, and use the name in the definition of f0012. You need to provide more details, if you need additional advice. $\endgroup$
    – bbgodfrey
    Feb 13, 2015 at 22:26
  • $\begingroup$ Welcome to Mathematica.SE! I suggest that: 1) You take the introductory Tour now! 2) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! 3) As you receive help, try to give it too, by answering questions in your area of expertise. $\endgroup$
    – bbgodfrey
    Feb 13, 2015 at 22:27
  • $\begingroup$ @Mr.Wizard♦ @bbgodfrey Example f[] added. $\endgroup$
    – jdaw1
    Feb 13, 2015 at 23:00
  • $\begingroup$ To force immediate evaluation first and then do pattern recognition later, do f0012[y0_, y1_, y2_, s_, d_] = FullSimplify[D[f[y0, y1, y2, s, d], {y0, 2}, {y1, 1}, {y2, 1}]];. After this, executing f0012[a, b, c, d, e] executes instantly, indicating that the computation isn't being done every time f0012 is called. Otherwise, by using := instead of =, the computation is done every time, which we don't want. Does this answer your question? $\endgroup$ Feb 13, 2015 at 23:27

1 Answer 1

1
$\begingroup$

I'll use your example Theta:

Theta[y0_, y1_, y2_, s_, d_] := 
  Total[(Exp[-#] (# + 1)^10) & /@ {y0, y1, y2, s, d}];

f[y0_, y1_, y2_, s_, d_] := (Pause[1]; 
   Log[Theta[y0, y1, y2, s, d]/constant]*
    Theta[y0, y1, y2, s, d]/D[Theta[y0, y1, y2, s, d], y0]);

To force evaluation first, use = instead of :=, like so:

f0012[y0_, y1_, y2_, s_, d_] = 
  D[f[y0, y1, y2, s, d], {y0, 2}, {y1, 1}, {y2, 1}];

I omitted the FullSimplify because it was taking too much time. After this, any symbolic call to f0012, such as f0012[a, b, c, d, e], executes instantly. Likewise, f0012[1.2, 2.3, 3.2, 1.1, 2.1] instantly executes to 117.806 (although I make no claims to accuracy here).

$\endgroup$
5
  • $\begingroup$ Does it preserve scope? If, before this stuff, y0=0.05 had been set, would that damage your method? $\endgroup$
    – jdaw1
    Feb 13, 2015 at 23:46
  • $\begingroup$ @jdaw1: Yup, in this case that would damage it, because you'd be taking derivative with respect to a symbol which was actually a floating-point number, which is a syntax error. But it should be easy enough to get around that. For example, if you are going to globally use y0 = 0.05, then why not just rename it y0global = 0.05 and then execute f0012[y1_, y2_, s_, d_] = D[f[y0, y1, y2, s, d], {y0, 2}, {y1, 1}, {y2, 1}] /. y0 -> y0global;? I.e., if y0 is going to globally be 0.05 then it seems not useful to have it as a variable parameter in your functions. Does that work? $\endgroup$ Feb 14, 2015 at 0:14
  • $\begingroup$ Unsurprisingly, the variable y0 appears in lots of places in my code. And if ever f0012[…] is called with y0 defined in some scope visible at time of calling, then f0012[…] will use the ‘external’ y0 rather than the passed ‘internal’ y0. That’s yuckier than copy-paste. Surely Mathematica can do better. $\endgroup$
    – jdaw1
    Feb 14, 2015 at 11:43
  • 1
    $\begingroup$ You could define your f0012 inside a Module or use formal symbols to define it. Those symbols can never be given a value and are perfect for safely defining functions. $\endgroup$ Feb 14, 2015 at 13:07
  • $\begingroup$ Upon checking, it works! f[…] = … does indeed evaluate symbolically now, but maintains scope for the apparent parameters. Thank you. $\endgroup$
    – jdaw1
    Feb 16, 2015 at 12:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.