Symbolic Evaluation

The functions (RefLink[FindMinimum, paclet:ref/FindMinimum]), (RefLink[FindMaximum, paclet:ref/FindMaximum]), and (RefLink[FindRoot, paclet:ref/FindRoot]) have the (RefLink[HoldAll, paclet:ref/HoldAll]) attribute and so have special semantics for evaluation of their arguments. First, the variables are determined from the second argument, then they are localized. Next, the function is evaluated symbolically, then processed into an efficient form for numerical evaluation. Finally, during the execution of the command, the function is repeatedly evaluated with different numerical values. Here is a list showing these steps with additional description.

Steps in processing the function for the "Find" commands.

(RefLink[FindFit, paclet:ref/FindFit]) does not have the (RefLink[HoldAll, paclet:ref/HoldAll]) attribute, so its arguments are all evaluated before the commands begin. However, it uses all of the stages described above, except instead of evaluating the function, it constructs a function to minimize from the model function, variables, and provided data.

You will sometimes want to prevent symbolic evaluation, most often when your function is not an explicit formula, but a value derived through running through a program. An example of what happens and how to prevent the symbolic evaluation is shown.

This attempts to solve a simple boundary value problem numerically using shooting:

FindRoot[First[x[1] /. NDSolve[{x''[t] + (x[t] UnitStep[t] +1)x[t] == 0, x[-1] == 0, x'[-1] == xp},x, {t,-1,1}]], {xp, Pi}]

The command fails because of the symbolic evaluation of the function. You can see what happens when you evaluate it inside of (RefLink[Block, paclet:ref/Block]).

This evaluates the function given to (RefLink[FindRoot, paclet:ref/FindRoot]) with a local (undefined) value of xp:

Block[{xp}, First[x[1] /. NDSolve[{x''[t] + (x[t] UnitStep[t] +1)x[t] == 0, x[-1] == 0, x'[-1] == xp},x, {t,-1,1}]]]

Of course, this is not at all what was intended for the function; it does not even depend on xp. What happened is that without a numerical value for xp, (RefLink[NDSolve, paclet:ref/NDSolve]) fails, so (RefLink[ReplaceAll, paclet:ref/ReplaceAll]) (/.) fails because there are no rules. (RefLink[First, paclet:ref/First]) just returns its first argument, which is x[1]. Since the function is meaningless unless xp has numerical values, it should be properly defined.

This defines a function that returns the value x[1] as a function of a numerical value for x'[t] at t=-1:

fx1[xp_?NumberQ] :=  First[x[1] /. NDSolve[{x''[t] +  (x[t]UnitStep[t] +1)x[t] == 0, x[-1] == 0, x'[-1] == xp},x, {t,-1,1}]]

An advantage of having a simple function definition outside of (RefLink[FindRoot, paclet:ref/FindRoot]) is that it can independently be tested to make sure that it is what you really intended.

This makes a plot of fx1:

Plot[fx1[xp], {xp, 0, 5}]

From the plot, you can deduce two bracketing values for the root, so it is possible to take advantage of Brent's method to quickly and accurately solve the problem.

This solves the shooting problem:

FindRoot[fx1[xp],{xp, 3,4}]

It may seem that symbolic evaluation just creates a bother since you have to define the function specifically to prevent it. However, without symbolic evaluation, it is hard for the Wolfram Language to take advantage of its unique combination of numerical and symbolic power. Symbolic evaluation means that the commands can consistently take advantage of benefits that come from symbolic analysis, such as algorithm determination, automatic computation of derivatives, automatic optimization and compilation, and structural analysis.