# How to efficiently evaluate only parts of an n dimensional function

Suppose I have a costy n dimensional function:

$f:\mathbb{R}\rightarrow \mathbb{R}^n$

like one of these two:

f[t_] = Array[BesselJZero[#1, #1*t] &, {150}];
g[t_] = Array[Nest[Sin, #*t, 100] &, {15000}];


I would like to evaluate only a part of them (lets say the first entry) as fast as possible. The naive way would be:

Code 1:

AbsoluteTiming[f[1.][]]
AbsoluteTiming[g[1.][]]


{0.617862, 3.83171}

{0.724064, 0.168852}

This is super slow since Mathematica calculates all entries and then takes the first value of it. So I tried something like:

Code 2

AbsoluteTiming[f[t][] /. t -> 1.]
AbsoluteTiming[(g[t][]) /. t -> 1.]


{0.0078714, 3.83171}

{0.591159, 0.168852}

This approach is fine for the function f because BesselJZero is a costy function itself but not hard to construct explicitly. What I don't quite get is why this approach is still slow for g. What I came up at the end and what seems to work is something like this:

Code 3

g2 = g[t];
f2 = f[t];
AbsoluteTiming[f2[] /. t -> 1.]
AbsoluteTiming[g2[] /. t -> 1.]


{0.0122119, 3.83171}

{0.000198283, 0.168852}

I would like to know:

• Whats the convenient way to deal with high dimensional functions and evaluating only parts of it?
• Why is g not sped up in Code 2? Its explicit form was already created by Set in the definition wasn't it? I would understand this if I used Unset but I didn't.
• How would you evaluate the first entry of f and g efficiently if they were interpolating functions?

Edit: To question 3 an example:

h = Interpolation[Table[{t, Array[Sin[#1 t] Cos[#2 t] &, {150, 150}]}, {t,0.5,1.5,.01}]];
AbsoluteTiming[h[1.][[1, 1]]]
AbsoluteTiming[Sin[1*#] Cos[1*#] &[1.]]


{0.0324101, 0.454649}

{0.0000106736, 0.454649}

Here I would like Mathematica to skip evaluating the whole function h, just the value 1,1 should be computed. The speed should be in the order of the second value. I have no equivalent here trying to extract the 1,1 component in beforehand as I did before with f and g.

• Evaluating g[t] is what takes the time. In Code 3 your evaluation of g[t] happens outside of the AbsoluteTiming. As for your last question, what is an example using interpolating functions? – Carl Woll Mar 20 '18 at 15:24
• Isn't the construction of g done when I define g via Set? And shouldn't then the explicite symbolic expression be saved in g? I added an example interpolating function h to the question. – Mr Puh Mar 20 '18 at 15:37
• I wonder if using Inactive in the definition of the function would help here? Select the part you want and then Activate the expression – chuy Mar 20 '18 at 16:27
• Can you express your function as a Series and retain just the first few (dominating) terms? – David G. Stork Mar 20 '18 at 16:53

As I said in my comment, the difference between your "Code 2" and "Code 3" timing is that "Code 3" doesn't include the timing to evaluate g[t]:

g2 = g[t]; //AbsoluteTiming


{0.456115, Null}

As for your question on interpolating functions, one idea is to modify the interpolating function before using it. Here is a function that modifies the interpolating function:

ifpart[h_, part__] := Module[{if=h},
if[] = h[[4, All, All, part]];
if
]


Compare:

h[1.001][[2,3]] //RepeatedTiming
hp = ifpart[h, 2, 3]; //RepeatedTiming
hp[1.001] //RepeatedTiming


{0.020, -0.89973}

{0.0000126, Null}

{3.0*10^-6, -0.89973}

• The nested List of g needs time to construct. I thought Set is only constructing this once while Unset constructs it for every call. And indeed when using Set the definition of g needs some time. When calling g[1.] then, I thought the evaluation of Nest and Array would not be needed anymore but it doesnt seem like it. Only when defining another explicite variable g2 really evaluates Nest and Array and saves the result as symbolic expression for later use. Dont understand why Set is not doing that in the first place. Thats what I meant in the comments earlier. – Mr Puh Mar 29 '18 at 14:14