# Semi-delayed assignment: analytic now; numeric later

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


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.

• 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. – Mr.Wizard Feb 13 '15 at 22:25
• 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. – bbgodfrey Feb 13 '15 at 22:26
• 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. – bbgodfrey Feb 13 '15 at 22:27
• @Mr.Wizard♦ @bbgodfrey Example f[] added. – jdaw1 Feb 13 '15 at 23:00
• 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? – DumpsterDoofus Feb 13 '15 at 23:27

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).

• Does it preserve scope? If, before this stuff, y0=0.05 had been set, would that damage your method? – jdaw1 Feb 13 '15 at 23:46
• @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? – DumpsterDoofus Feb 14 '15 at 0:14
• 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. – jdaw1 Feb 14 '15 at 11:43
• 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. – Sjoerd C. de Vries Feb 14 '15 at 13:07
• Upon checking, it works! f[…] = … does indeed evaluate symbolically now, but maintains scope for the apparent parameters. Thank you. – jdaw1 Feb 16 '15 at 12:42