What is the role of the pattern object in this implementation?

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.

=================

1

 

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.
– abrentonc
Jun 25 ’15 at 19:11

1

 

NonlinearModelFit does not have any Hold* attributes, so your code evaluates model[a, b, c] with symbolic arguments before NonlinearModelFit “sees” it.
– Simon Woods
Jun 25 ’15 at 19:41

=================

2 Answers
2

=================

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}]]

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]

  

 

Why does the NonlinearModelFit seem to be running the function on non-numbers though?
– abrentonc
Jun 25 ’15 at 18:48

  

 

reference.wolfram.com/language/tutorial/…, The definition applies only when the variable has a numerical argument.
– Enrique Pérez Herrero
Jun 25 ’15 at 18:57

1

 

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.
– abrentonc
Jun 25 ’15 at 19:08

  

 

Quit the Kernel and try again
– Enrique Pérez Herrero
Jun 25 ’15 at 19:09

  

 

Fresh kernel didn’t help
– abrentonc
Jun 25 ’15 at 19:13