Message Boards Message Boards

What's the difference between plotting and solving?

GROUPS:

Hello community,

this is something that's been bugging me for a long time, I simply don't get it: Why can Mathematica plot some functions without any problem, but not numerically solve an equation containing this function? I mean, I can see that Mathematica obviously calculated the values for plotting. Now why can't NSolve just use these values, compare them to the value I want to solve for (e.g., 0) and then tell me for which x the function f(x) is closest to 0? I had to build my own functions doing exactly that, and that's cumbersome and very prone to errors since I'm not a programmer.

Any insight provided to me about this issue is appreciated!

POSTED BY: Sebastian Neumann
Answer
2 months ago

Sebastian,

Nsolve always works for me. Please give an example of code that has an issue so we can see how you are using it.

Regards

POSTED BY: Neil Singer
Answer
2 months ago

As already noted, it is difficult to respond to a question like this in absence of code for an example. Taking a guess I would surmise that no restriction was given to NSolve for where the solutions(s) might be located (Reals, an interval of the form a<=x<=b, etc.) and if the unrestricted solution set is perhaps infinite it cannot give a result.

POSTED BY: Daniel Lichtblau
Answer
2 months ago

Another reason is that they use different algorithms and sometimes domains (Complexes, Reals).

For a Plot-like solver for the real roots of a smooth function over an interval, consider this:

{x -> #} & /@ Reap[
   NDSolve[{y'[x] == f, y[a] == (f /. x -> a), 
     WhenEvent[f == 0, Sow[x, "root"]]}, {}, {x, a, b}],
   "root"
   ][[2, 1]]

WhenEvent uses FindRoot under the hood. Of course it might well miss double roots, just like Plot, that NSolve might actually catch.

Example:

NSolve[Re@PolyLog[2, x] - Sin[x] + x/10 == 0 && 1 < x < 100, x]
(*
NSolve::nsmet: This system cannot be solved with the methods available to NSolve.

NSolve[x/10 + Re[PolyLog[2, x]] - Sin[x] == 0 && 1 < x < 100, x]
*)

ClearAll[nsolve];  (* general solver based on the above idea *)
nsolve[eq_, {x_, a_, b_}] := Module[{y},
  With[{f = eq /. Equal -> Subtract},
   {x -> #} & /@ Reap[
      NDSolve[{y'[x] == f, y[a] == (f /. x -> a), 
        WhenEvent[f == 0, Sow[x, "root"]]}, {}, {x, a, b}],
      "root"
      ][[2, 1]]
   ]];

roots = nsolve[Re@PolyLog[2, x] - Sin[x] + x/10 == 0, {x, 1, 100}]
(*
{{x -> 19.7212}, {x -> 21.2187}, {x -> 25.7155}, {x -> 27.743}, {x -> 
   31.8867}, {x -> 34.0993}, {x -> 38.1639}, {x -> 40.3583}, {x -> 
   44.523}, {x -> 46.5435}, {x -> 50.9595}, {x -> 52.6584}, {x -> 
   57.4995}, {x -> 58.675}}
*)

Plot[Re@PolyLog[2, x] - Sin[x] + x/10, {x, 1, 100}, 
 Mesh -> {x /. roots}, MeshStyle -> Red]

enter image description here

POSTED BY: Michael Rogers
Answer
2 months ago

Ted Ersek's package RootSearch fills in quite nicely for the missing built-in functionality.

POSTED BY: Gianluca Gorni
Answer
2 months ago

Yes, I have never understood why Ted's RootSearch code has not been made part of regular Mathematica! In my experience it works very well, finding multiple roots - crossings and zeros, and even though it's specialized to searching along a line this is one of the most common applications and IS missing functionality. Also, I don't understand why FindRoot, when given a domain doesn't stay within the domain.

POSTED BY: David J M Park Jr
Answer
2 months ago

In this Stackexchange answer, Adam Strzebonski showed a way to get complex roots from System`TRootsDump`GuessRoots[f, {a, b}, False], where f is a pure function. For real roots one can use System`TRootsDump`GuessRealRoots[f, {a, b}]. These use ContourPlot and Plot respectively to approximate the roots. The results can be polished with FindRoot.

It's not clear to me how they plug into the high-level solvers.

POSTED BY: Updating Name
Answer
2 months ago

Group Abstract Group Abstract