Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm learning MMA with Wagner's book. On page 41, he uses this to display the iterative steps of a FindRoot. However, I can't seem to replicate this (code at end), perhaps due to the difference in MMA versions (his was MMA 3.0!). Using Trace doesn't seem to help; it just displays the final value of x.

FindRoot iteration Trace

Codes:

FindRoot[Print[x]; Sin[x] - Cos[x], {x, 0.5}]
Trace[FindRoot[Sin[x] - Cos[x], {x, 0.5}]]

Edit I have also tried to use his method--Print[x] within a function--for an exercise in the section and that seems to work (though with some quirk in the result). EvaluationMonitor also works, and frankly I find the latter much more intuitive. Below is my solution for the problem (code at end); I'm not sure if this is the way Sin[x] is actually sampled, so any feedback is very welcome.

Sin[x] sampling animation EvaluationMonitor

Plot[Sin[x], {x, \[Pi]/4, \[Pi]/2}] // InputForm
Plot[Print[x]; Sin[x], {x, \[Pi]/4, \[Pi]/2}]
Reap[Plot[Sow[x]; Sin[x], {x, \[Pi]/4, \[Pi]/2}]][[2]]
{plot, List@stepValue} = 
  Reap[Plot[Sin[x], {x, \[Pi]/4, \[Pi]/2}, 
    EvaluationMonitor :> Sow[x]]];
stepValuePoints = {stepValue, Sin[stepValue]} // Transpose;
ListPlot[stepValue, AxesLabel -> {Step, x}]
Manipulate[
 Show[
  (* Actual y = Sin[x] curve *)
  Plot[Sin[x], {x, \[Pi]/4, \[Pi]/2}, PlotStyle -> Yellow],
  (* Generated mesh points *)
  ListPlot[stepValuePoints, PlotStyle -> Red],
  (* Arrow tail *)
  ListLinePlot[{Table[stepValuePoints[[i]], {i, step - 5, step - 1}]}],
  (*Arrow head *)
  Graphics@{Blue, 
    Arrow[{stepValuePoints[[step - 1]], stepValuePoints[[step]]}]},
  PlotRange -> {{\[Pi]/4, \[Pi]/2}, {Sqrt[2.]/2, 1}}], {step, 6, 
  Length[stepValuePoints], 1}]
anim = Table[
   Show[
    (* Actual y = Sin[x] curve *)
    Plot[Sin[x], {x, \[Pi]/4, \[Pi]/2}, PlotStyle -> Yellow],
    (* Generated mesh points *)
    ListPlot[stepValuePoints, PlotStyle -> Red],
    (* Arrow tail *)
    ListLinePlot[{Table[
       stepValuePoints[[i]], {i, step - 5, step - 1}]}],
    (*Arrow head *)
    Graphics@{Blue, 
      Arrow[{stepValuePoints[[step - 1]], stepValuePoints[[step]]}]},
    PlotRange -> {{\[Pi]/4, \[Pi]/2}, {Sqrt[2.]/2, 1}}], {step, 6, 
    Length[stepValuePoints], 1}];
Export["anim.gif", anim, "DisplayDurations" -> 0.25]
share|improve this question
3  
Have a look at the EvaluationMonitor option. –  b.gatessucks Jun 21 at 21:17
    
Thank you b.gatessucks! That works for me. –  seismatica Jun 21 at 21:24
add comment

3 Answers 3

up vote 6 down vote accepted

EvaluationMonitor works in this case (per b.gatessucks' helpful suggestion). StepMonitor also works although it doesn't display the starting value.

EvaluationMonitor StepMonitor

Code

FindRoot[Sin[x] - Cos[x], {x, 0.5}, 
 EvaluationMonitor :> Print["x=", x, ", y=", Sin[x] - Cos[x]]]

FindRoot[Sin[x] - Cos[x], {x, 0.5}, 
 StepMonitor :> Print["x=", x, ", y=", Sin[x] - Cos[x]]]
share|improve this answer
    
oops sorry I forgot! Code added. –  seismatica Jun 21 at 21:33
add comment

EvaluationMonitor (and StepMonitor) have been mentioned, but not every function has these options. So here's a more general way:

You need to prevent the function from evaluating for non-numeric arguments. This is a very very common issue described here among other places.

Solution 1:

f[x_?NumericQ] := (Print[x]; Sin[x] - Cos[x])

FindRoot[f[x], {x, .5}]

Solution 2:

I don't always like to define a new function for a one-time-use scenario. I quite like David Bailey's When function suggested here, and I have it (as well as some variations) in my personal toolbox.

FindRoot[When[NumericQ[x], Print[x]; Sin[x] - Cos[x]], {x, .5}]

There's yet another way, specific to FindRoot (as well as many plotting functions). use Evaluated -> False:

FindRoot[Print[x]; Sin[x] - Cos[x], {x, .5}, Evaluated -> False]
share|improve this answer
    
Thank you so much for your help Szabolcs! If I understand NumericQ correctly, the reason why the code in my question does not work is because Print[x] is evaluated first to display the symbol "x" and so it can't print any more iterative values of x in the future. But doesn't FindRoot have a HoldAll attribute so x would be substituted first before it is printed. I'm very new to MMA so I'm very confused by the order of calculation in MMA. PS: For some reason doing it the way you showed me gave more iteration values- screen- not sure why that is. –  seismatica Jun 22 at 0:23
    
@seismatica If a function does not have HoldAll, it means that it's argument will surely get evaluated before the function sees it. If FindRoot didn't have HoldAll, we could be certain that this code prints x precisely once, and then nothing else. This is already clear to use. However, if a function does have HoldAll, it only means that the function is free to do whatever with its argument, as it receives it in unevaluated form. It can evaluate it if it wishes. It can keep it unevaluated. Or it can let evaluation be controlled by an option. –  Szabolcs Jun 22 at 0:26
    
@seismatica Here's an example of a HoldAll function that does evaluate it's argument: SetAttributes[fun1, HoldAll]; fun1[expr_, x_ -> value_] := Unevaluated[expr] /. x -> value. And here's one that doesn't: SetAttributes[fun2, HoldAll]; fun2[expr_, x_ -> value_] := expr /. x -> value. Also see my update to the answer. –  Szabolcs Jun 22 at 0:30
1  
It might be worth mentioning that FindRoot uses different methods with f[x_?NumericQ] :=... and f[x_] := ... in this case, and the evaluations of f are different. It can't use Newton's Method with the NumericQ definition unless one explicitly passes the Jacobian: df[x_] := Evaluate@{{D[Sin[x] - Cos[x], x]}}; FindRoot[f[x], {x, .5}, Jacobian -> df[x]]. –  Michael E2 Jun 22 at 3:52
    
I might be wrong, but shouldn't your fun2 not be set with HoldAll attribute? About the FindRoot function, my question is since it already has the HoldAll attribute, would each iteration then pass a value of x on to Print[x]--which had yet been evaluated, otherwise it would just return "x"--and hence that value would be displayed? I'm not really sure how FindRoot works so I may not even know what I'm talking about, so if you could explain to me how NumericQ solves my problem (though you're certainly not obligated to), I'd really appreciate it. –  seismatica Jun 22 at 3:56
show 1 more comment

If you are also interested in easy way of viewing the points on figure, you can also use

<< Optimization`UnconstrainedProblems package.

This package runs the optimization function (like FindRoot), keeps track of the function and gradient evaluations and steps taken during the search (using the EvaluationMonitor and StepMonitor options), and shows them superimposed on a plot of the function.

<< Optimization`UnconstrainedProblems`
FindRootPlot[Sin[x] - Cos[x], {x, 0.5}, ImageSize -> 600, 
 PlotRange -> {-0.5, 0.1}]
share|improve this answer
    
Another neat tip. Thank you so much Algohi! –  seismatica Jun 22 at 3:59
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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