I am using Mathematica's FindFit function to fit a parametric solution to my data and I am getting the error

FindFit::nrnum: The function value [complicated expression] is not a real number at {ka,kd,beta} = {0.7,0.1,0.1}

he initial guesses of the parameters {ka=0.7,kd=0.1,beta=0.1} are very close to the values I used to mock up the data, and I can't figure out where I am going wrong. I posted a similar version of this question on stack exchange but didn't get any response.

First I use the ParametricNDSolveValue function to parametrically solve two coupled first order differential equations for the functions 'a[t]' and 'b[t]' with parameters ka, kd, and beta:

sol = ParametricNDSolveValue[{D[a[t], t] == -kd*a[t] + ka*(1 - a[t] - b[t]), a[0] == ka/(ka + kd), 
  D[b[t], t] == -kd*b[t] + ka*(1 - Exp[-beta*t]) (1 - a[t] - b[t]), b[0] == 0 }, {a, b}, 
  {t, 0, 20}, {ka, kd, beta}]

I can extract the solution for a[t] for ka=0.7, kd=0.1, beta=0.1 by using:

y1 = sol[0.7, 0.1, 0.1][[1]]

Plotting y1 as a function of t gives the expected curve:

Plot[y1[t], {t, 0, 20}, PlotRange -> All]

Then I create a data table eyeballing the values from the above plot:

dataA = {{0, 0.87}, {5, 0.84}, {10, 0.75}, {15, 0.68}, {20, 0.62}}

Finally to test FindFit, I use FindFit with sol[ka, kd, beta][[1]][t] to fit the data giving the same initial values for ka, kd, and beta that I used to generate the above data:

fit = FindFit[dataA, sol[ka, kd, beta][[1]][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

At which point I get the error:

FindFit::nrnum: "The function value 1/2\ ((-0.87+Abs[0.7[0.]])^2+(-0.84+Abs[0.7[5.]])^2+(-0.75+Abs[0.7[10.]])^2+(-0.68+Abs[0.7[15.]])^2+(-0.62+Abs[0.7[20.]])^2) is not a real number at {ka,kd,beta} = {0.7,0.1,0.1}."

I tried using Abs[sol[ka, kd, beta][[1]][t]] in FindFit, that didn't work. Then I tried adding constraints:

fit = FindFit[dataA, {Abs[sol[ka, kd, beta][[1]][t]], {ka > 0, kd > 0, 
  beta > 0}}, {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

And that failed too.

Any clues what is wrong with my code? Thanks a lot!

  • $\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
    Commented Feb 3, 2015 at 17:42
  • $\begingroup$ Take a close look at your error output message. Your variable substitution is problematic and you end up with terms like Abs[0.7[5.]] repeatedly. 0.7 is not a function and cannot be addressed as such. $\endgroup$ Commented Feb 3, 2015 at 20:00

2 Answers 2

sol = ParametricNDSolve[{D[a[t], t] == -kd*a[t] + ka*(1 - a[t] - b[t]), a[0] == ka/(ka + kd), 
                        D[b[t], t] == -kd*b[t] + ka*(1 - Exp[-beta*t]) (1 - a[t] - b[t]), 
                        b[0] == 0}, {a, b}, {t, 0, 20}, {ka, kd, beta}];

dataA = {{0, 0.87}, {5, 0.84}, {10, 0.75}, {15, 0.68}, {20, 0.62}};

fit = FindFit[dataA, a[ka, kd, beta][t] /. sol, {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]

 (* {ka -> 0.932926, kd -> 0.136649, beta -> 0.0603393} *)

Plot[{a[.7, .1, .1][t] /. sol, a[ka, kd, beta][t] /. fit /. sol}, {t, 0, 20}, PlotRange -> All]

Mathematica graphics

  • $\begingroup$ +1 But could you explain why the result of 'ParametricNDSolveValue' isn't working here? $\endgroup$
    – Matariki
    Commented Feb 3, 2015 at 20:34
  • $\begingroup$ @Matariki I haven't tried it :) $\endgroup$ Commented Feb 3, 2015 at 20:44
  • $\begingroup$ @belisarius Thanks a lot, this worked! I think my syntax of finding "the solution for a[t]" from ParametricNDSolveValue is incorrect, i.e. it is incorrect to use sol[ka, kd, beta][[1]][t] in FindFit, but I don't know why. Also, an excellent post by @Oleksandr R. on the question of simultaneously fitting multiple datasets with a parametric solution of coupled differential equations can be found here: link $\endgroup$
    – Sam
    Commented Feb 3, 2015 at 21:13
  • $\begingroup$ @Sam Glad to hear it helped $\endgroup$ Commented Feb 3, 2015 at 21:15

The problem is that sol[ka, kd, beta][[1]][t] evaluates to ka[t] before numeric values are substituted for the parameters. You need to prevent evaluation of [[1]] until after sol has evaluated to a list of solutions.

Thanks to Mr.Wizard for pointing out Indexed, which will do what we're after.

fit = FindFit[dataA, Indexed[sol[ka, kd, beta], 1][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]
(*  {ka -> 0.932928, kd -> 0.136649, beta -> 0.0603392}  *)

In pre-V10, something like this will work (original answer):

firstIfList[l_List] := First[l]

fit = FindFit[dataA, firstIfList[sol[ka, kd, beta]][t], {{ka, 0.7}, {kd, 0.1}, {beta, 0.1}}, t]
(*  {ka -> 0.932928, kd -> 0.136649, beta -> 0.0603392}  *)

See Prevent Part[] from trying to extract parts of symbolic expressions for a similar issue with Part.

  • $\begingroup$ Indexed[sol[ka, kd, beta], 1][t] also works. $\endgroup$
    – Mr.Wizard
    Commented Feb 4, 2015 at 11:43
  • $\begingroup$ @Mr.Wizard Thanks! I knew there was something new that solved this problem, but I forgot the name. $\endgroup$
    – Michael E2
    Commented Feb 4, 2015 at 11:44
  • $\begingroup$ It's in this answer in the Q&A you linked, if you'd like to vote for it. ;^) $\endgroup$
    – Mr.Wizard
    Commented Feb 4, 2015 at 11:45
  • 1
    $\begingroup$ @Mr.Wizard Oops! I didn't read far enough. +1. :) $\endgroup$
    – Michael E2
    Commented Feb 4, 2015 at 11:46
  • $\begingroup$ Thanks everybody for answering my questions! Good to know about Indexed! $\endgroup$
    – Sam
    Commented Feb 4, 2015 at 18:30

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.