Fitting minimizer exception

Expected behavior

A call to the Fit algorithm should not crash if given reasonable guesses for initial parameters. If the minimizer calculates new trial parameters of NaN or Inf it should ideally try a more modest change, or explain clearly (by reporting Failed to Converge or similar) why my function is faulty.

Actual behavior

I sometimes get a red error message such as “Trying to set a NaN value (-nan(ind)) to parameter n”.

Putting MaxIterations=0 makes Fit reproduce my initial guess which looks reasonable (and for the benefit of the Poisson cost function, is positive everywhere)

Steps to reproduce the behavior

I’m using a User Function and the Poisson cost function (and the Levenberg-MarquardtMD minimizer), to fit raw muon data. For example
Function='Name=UserFunction, Formula=1/(1/(n*(1+a*cos(x*8.16633892558+p))*exp(-x/tau)+b)+d), n=24133.0, a=0.2, p=-0.226184558207, b=0.01, d=0.00001, tau=2.19703'

Platforms affected

Mantid 4.2 and possibly others, tried both in a script and with the Fit algorithm dialog

Hi James,

Since it’s a user defined function,the first thing I’d like to check is, are you sure that the x values in the data you intend to use this on are small enough to ensure that (8x-0.2) doesn’t produce cos(>1) ?

It’s cos(x) which is valid for all x, not acos(x) which does require |x|<=1. I would expect in this case that we get cos(0) to about cos(260) or 42 oscillations (as seen in the raw data). And the fit does work at times, and even when it would have failed it evaluates the initial guess correctly if I set Max Iterations=0.

I suspect the Poisson cost function may be involved. Changing back to Least Squares makes it converge more reliably although the answer will be slightly wrong - which is why I updated my script to use Poisson now it’s available. Poisson will probably return Cost=NaN if updated parameters make the function negative anywhere. That might be either on a subsequent iteration, or if the fitting minimiser is making a change in order to calculate derivatives. If the latter, can it be a bit more intelligent: if (f(x+eps)-f(x))/eps gives NaN then try (f(x-eps)-f(x))/(-eps) instead?

An issue has been created for this: Poisson Nan values · Issue #27564 · mantidproject/mantid · GitHub