3

I have a really big vector (nearly 30,000 elements) called x and am trying to numerically find the root of a function where one of the parameters successively takes each value stored in the vector. At the moment, I'm using a For loop (I know a lot of people here cringe at the very mention of For loops for some reason; sorry):

For[j=1,j<=Length[x],j++,
 f = SOME REALLY COMPLICATED FUNCTION OF t AND x[[j]];
 sol[[j]]=t/.FindRoot[f,{t,t0}];
 Clear[t];
];
Print[sol];

I'm wondering whether there's a more efficient way of doing this (I'm talking code-wise, not things like some simple approximation to f which gives an acceptably small error). Currently, my code takes just over 5 minutes to run (I've got a few more operations before and after the numerical bit, but they don't take long, so perhaps the numerical bit takes 4-5 minutes). I've tried setting it up as a vector operation (see code below), but after about 10 minutes of evaluation I quit the kernel because it was clear to me that that wasn't going to be more efficient than the For loop. Here's my vector-operation code:

f = SOME REALLY COMPLICATED FUNCTION OF t AND x;
sol=t/.FindRoot[f,{t,t0}]
Print[sol];

Thanks in advance.

Rain
  • 636
  • 3
  • 12
  • 2
    (a) People cringe because of this. (b) Consider parallelization, i.e. sol=ParallelTable[t/.FindRoot[SOME REALLY COMPLICATED FUNCTION OF t AND x[[j]],{t,t0}],{j,Length[x]}]. (c) Consider Compile. – yohbs May 23 '17 at 15:47
  • 2
    Best bet would be to focus on different settings for FindRoot that might improve its performance. That is almost certainly where the bottleneck lies. – Daniel Lichtblau May 23 '17 at 16:03
  • If the solutions working through the x vector are not far off from each other, use the last t as the start point for the next FindRoot iteration. – MikeY May 23 '17 at 16:25
  • @yohbs Thanks! That reduces the time the code takes to run by a factor of about 2.5. That's exactly what I was looking for. :) What does Compile do and how do I use it? – Rain May 23 '17 at 17:13
  • @DanielLichtblau I'm pretty sure I can't do any better with respect to t0. Is there anything else I can do to optimise it? – Rain May 23 '17 at 17:15
  • @MikeY That's a good suggestion, but all the solutions are within about 0.01 of t0 (which is about 1.42), so I'm not sure setting each value of t as the starting point for the next FindRoot would make a big difference. – Rain May 23 '17 at 17:20
  • 1
    Compile (link) does, as its name suggests, compilation. It takes a series of mathematica commands and compiles them to machine language which is more efficient in terms of running time. Two things: If this will do anything, it will probably mainly accelerate the COMPLICATED FUNCTION and not FindRoot, so if the bottleneck is in FindRoot I wouldn't bother. Second, not all mathematica's commands are compilable so this might not work for you. – yohbs May 23 '17 at 18:29
  • 2
    If you can take derivatives of f, you could recast the problem as an ODE, and then the output of NDSolve will give you an interpolating function that can be used on your vector. – Carl Woll May 23 '17 at 19:33
  • @yohbs Thanks for the link. My bottleneck is definitely in FindRoot, so no point using Compile, then, but it's good to know there's that option. – Rain May 24 '17 at 17:19
  • @CarlWoll Thanks! I'll see whether that helps. – Rain May 24 '17 at 17:19

0 Answers0