1
$\begingroup$

In the documentation I found a nice idiom which allows me to do model fitting with interpolating functions. I think this kind of thing is amazing and a credit to the utility of an environment like Mathematica. It goes like this:

model[a_?NumberQ, b_?NumberQ, c_?NumberQ] :=  
Module[{y, x}, 
First[y /. 
NDSolve[{y''[x] + a y[x] == 0, y[0] == b, y'[0] == c}, 
y, {x, 0, 10}]]]

nlm = NonlinearModelFit[data, model[a, b, c][x], {a, b, c}, x]

I think I understand how this works but my question is this: what is the significance of the pattern object ?NumberQ when model is first defined? For example my initial implementation of this was as follows:

model[a_ ,t_] :=  
Module[{y, x}, 
First[y /. 
NDSolve[{a(y'[x] t + y[x] == vtest, y[0] == 0}, 
y, {x, 0, end}]
]]

This is a just a different diff eq where vtest and end are given values ahead of time. But if I run this through the NonlinearModelFit without the ?NumberQ pattern on the initial model definition I get an NDSolve error saying that it encountered a non-numerical derivative at x$16212==0. I know how to avoid this I just don't understand why it doesn't work. Any help understanding what this error message indicates and what the role of the pattern object is would be much appreciated.

$\endgroup$
2
  • 1
    $\begingroup$ I understand the basic idea of pattern matching. My question has more to do with what NonlinearModelFit is doing to cause "model" to be evaluated with non-numerical arguments and why this results in the error it does. $\endgroup$
    – abrentonc
    Jun 25 '15 at 19:11
  • 1
    $\begingroup$ NonlinearModelFit does not have any Hold* attributes, so your code evaluates model[a, b, c] with symbolic arguments before NonlinearModelFit "sees" it. $\endgroup$ Jun 25 '15 at 19:41
3
$\begingroup$

Actually since version 9 there is ParametericNDSolve and NDSolveValue which both make the mentioned idiom even more attractive and doesn't even need the pattern matching you are struggling with:

model = Module[{x, y, a, t}, 
  ParametricNDSolveValue[
    {a*(y'[x] t - y[x]) == 7, y[0] == 0}, y, {x, 0, 1}, {a, t}
  ]
]

data = {#, model[0.5, 0.6][#] + RandomReal[0.00025]} & /@ Range[0, 1, 0.025];

fit = Module[{a,t},NonlinearModelFit[data, model[a, t][x], {a, t}, x]]

fit@"BestFitParameters"
Show[ListPlot[data], Plot[fit[x], {x, 0, 1}]]
$\endgroup$
2
$\begingroup$

The function checks if the input is a number (NumberQ), otherwise it prints out an error.

The function is only defined if the input is a number.

Please check this alternate example:

f[x_?OddQ] := "Here the function is defined for an odd number";
f[3]

But the function it is not defined for an even number:

f[2]
$\endgroup$
6
  • $\begingroup$ Why does the NonlinearModelFit seem to be running the function on non-numbers though? $\endgroup$
    – abrentonc
    Jun 25 '15 at 18:48
  • $\begingroup$ reference.wolfram.com/language/tutorial/…, The definition applies only when the variable has a numerical argument. $\endgroup$ Jun 25 '15 at 18:57
  • 1
    $\begingroup$ I think I understand pattern matching. I'm just not sure I understand why the kernel would ever attempt to evaluate the expression with non-numerical arguments int the model[a_,t_] expression and why this results in the error that I mention. $\endgroup$
    – abrentonc
    Jun 25 '15 at 19:08
  • $\begingroup$ Quit the Kernel and try again $\endgroup$ Jun 25 '15 at 19:09
  • $\begingroup$ Fresh kernel didn't help $\endgroup$
    – abrentonc
    Jun 25 '15 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.