2

I am trying to program Newton's Method in Mathematica to compute the roots of $f(x)=x^3-6x^2+11x-6$ using the Do command but my code gives a General::ivar error and doesn't work and I can't figure out what is wrong with it:

f[x_] := x^3 - 6*x^2 + 11*x - 6
g[x_] := D[f[x], x]
a[0] = 0;
Do[a[n + 1] = a[n] - N[f[a[n]]/g[a[n]]], {n, 0, 100}]

Table[a[n], {n, 0, 100}]

Can you explain what's wrong with it?

Michael E2
  • 235,386
  • 17
  • 334
  • 747
  • 3
    g[x_] = D[f[x], x] works, but the reasoning is a bit complicated for a comment. See Set vs SetDelayed in the documentation. This also might help with that: https://mathematica.stackexchange.com/questions/18393/what-are-the-most-common-pitfalls-awaiting-new-users/18487#18487 – eyorble Jan 04 '22 at 19:47

2 Answers2

4

This would be more idiomatic:

Clear[f, g, newtonIteration]

f[x_] := x^3 - 6x^2 + 11x - 6 g[x_] = D[f[x], x];

newtonIteration[previousEstimate_] := previousEstimate - f[previousEstimate]/g[previousEstimate]

FixedPointList[ newtonIteration, 0. (* starting value ), 100 ( max number of iterations *) ]

(* Out: {0., 0.545455, 0.848953, 0.974674, 0.999092, 0.999999, 1., 1., 1.} *)

Even shorter, with pure functions:

FixedPointList[# - f[#]/g[#] &, 0., 100]

The third argument of FixedPointList (the 100) is there to as a fail-safe, to stop runaway iterations that do not converge after 100 steps.

You want to use Set (=) instead of SetDelayed (:=) here to define the derivative g, so it is calculated symbolically and stored in g, and then numerical values of x are substituted as needed. On the other hand, using SetDelayed (:=) forces the re-calculation of the derivative at each step. In particular, this means that x will have already been assigned a numerical value at that point. and it will no longer be a valid variable for differentiation. This was the origin of the error in your original code.

MarcoB
  • 67,153
  • 18
  • 91
  • 189
1

To answer your question:

Notice the change in definition of f[x], g[x]

Clear[f, g, a]
f[x_] = x^3 - 6*x^2 + 11*x - 6
g[x_] = D[f[x], x]
a[0] = 0;
Do[a[n + 1] = a[n] - N[f[a[n]]/g[a[n]]], {n, 0, 7}]
Table[a[n], {n, 0, 7}]

{0, 0.545455, 0.848953, 0.974674, 0.999092, 0.999999, 1., 1.}


Save your work before you run such loops.

To help you understand it further:

Clear[f, g, a]
f[x_] = x^3 - 6*x^2 + 11*x - 6
g[x_] = D[f[x], x]
a[0] = 0;
Do[a[n + 1] = a[n] - N[f[a[n]]/g[a[n]]];
 Echo[a[n] , "a[" <> ToString@n <> "] = "];
 Pause[1];
 , {n, 0, 10}]

Now you can try with the SetDelayed := and see the difference.

Keep the Pause in there or it would be hard to abort evaluation in cases where it misbehaves.

Syed
  • 52,495
  • 4
  • 30
  • 85