Finding the roots isn't so easy

fsolve(x^2/20-10*x-15*cos(x+15),x);

1.274092075

I know to get maple to give me the other root I have graphically examine the funtion to see that it's around 200.  I need to use fsolve using x=190..210 to find it.  But that's a bit of a pain, I don't want to have to graph the function everytime, if my limits aren't far enough I may not find it. 

The Student[Calculus1] package won't find the roots using Roots since I believe it only deals with simple trigonometric functions.  Using solve I get a RootOf answer but it won't show me the numeric roots. 

What I want, is to find the roots without having to specify a range.  I could be missing something simple here but I'm stuck.  Anyone have some suggestions? 

avoid

> r1 := fsolve(x^2/20-10*x-15*cos(x+15),x);
                               r1 := 1.274092075

> fsolve(x^2/20-10*x-15*cos(x+15),x=0..infinity,avoid={x=r1});
                                  200.1193789
Axel Vogt's picture

besides 'avoid'

besides 'avoid' one (here) can use Maple to solve for an un-equality to find the search range:

x^2/20-10*x<=15; [solve(%, x)]; evalf(%);

                                   1/2              1/2
            [RealRange(100 - 10 103   , 100 + 10 103   )]
which is ~ -2 ... +202
gulliet's picture

Also, RootFinding:-Analytic might be a possible approach


> restart;
> RootFinding:-Analytic((1/20)*x^2-10*x-15*cos(x+15), x, re = -1000 .. 1000, im = -1 .. 1);
1.27409207502708, -1.80895918513793 - 0.959196521549030 I,

-1.80895918513793 + 0.959196521549025 I, 200.119378915794

HTH,
-- Jean-Marc

drawbacks

The usual drawbacks to RootFinding:-Analytic are that it is slower and that the complex values get in the way if only purely real roots are wanted.

On the one hand, the "complex box" that Analytic computes over should not be taken very "thin" (very narrow imaginary range) as that can produce numerical difficulties in calculating the contour integrals (residues). On the other hand, making the complex box wide enough to compute safely (and then easily using select and fnormal to sieve out the nonreal results) can make it slow.

gkokovidis's picture

Student[Calculus1]

Use the numeric option when calling Roots, from the Student[Calculus1] package, over the range of interest.

>restart:
>with(Student[Calculus1]):
>Roots(x^2/20-10*x-15*cos(x+15),x=0..210,numeric);

[1.274092075, 200.1193789]

Regards,
Georgios Kokovidis
Dräger Medical


quite so

Yes, and it's possible to view the source code and see that Student:-Calculus1:-Roots is itself calling fsolve with its avoid option.

I might have expected RootFinding:-NextZero to also get the next real root for this example.

Student[Calculus1]

Thanks for all the options.  It seems like using Student[Calculus1] Roots seems to be the best option.

Using fsolve with avoid will still miss some roots if there are more than one root within the range. 

In my opinion I think fsolve should return all roots within a specified range.  Even if I use solve, I get a RootOf answer that I can't seem to coax out the real numbers for the roots. 

solve(x^2/20-10*x-15*cox(15+x));

-15 + RootOf( -300 cos(_Z) + 3225 - 230 _Z + Z^2)

 

acer's picture

Roots

Student:-Calculus1:-Roots does in fact use fsolve with the avoid option. (But it uses it cleverly and repeatedly, until it ascertains that no more roots are in each generated subinterval.)

It's been for many years and Maple major releases that fsolve has, by default, returned only a single solution for the case of anything by a univariate polynomial. Changing that default would break a lot of users' code, so is a Bad Idea. Allowing it with some new syntax, such as fsolve(...,maxsols=all, <ranges>) might be ok.

Student:-Calculus1:-Roots is not bad, but one can write a 20 line procedure that is measurably faster, using RootFinding:-NextZero. You might also try the routine from Robert Israel's Maple Advisor Database which computes all real roots on a finite range.

acer

Thanks for the clear explanation

Thanks for the clear explanation.  I understand now why Maple returns only a single value.

NextZero

I get a fast failure:

r1 := fsolve(x^2/20-10*x-15*cos(x+15),x);

                          r1 := 1.274092075

RootFinding:-NextZero(x->x^2/20-10*x-15*cos(x+15),r1);

                                 FAIL

There is an option to make it work:

RootFinding:-NextZero(x->x^2/20-10*x-15*cos(x+15),r1,maxdistance=200);

                             200.1193789

But then you need some additional bound information.

Axel Vogt's picture

which is not too difficult

which is not too difficult, since cos is between +-1

BTW: I still do not understand, what is the reason for the original question, neither in this thread nor in the related one.

All roots with one simple command

The reason for the original question was to find a simple command that returned all the roots (mainly real) and Student(Calculus1) seems to do that quite well. Using fsolve doesn't always seem to return all the roots and only then some extra work is needed to be done to find them (ie examining a graph and specifying limits around each axis crossing to get a root - not the most efficient way of course).

Not difficult for a human

But I wonder whether such bound estimates could be automated. I.e. algorithmically implemented, beyond simple cases like this one (linear in 'cos'), for writing a reliable procedure. Sounds to me that some automated proving capabilities would be needed. And Maple is rather weak in this field. 

Axel Vogt's picture

all roots ... no chance

Normal
0
21

All roots? ... no chance ... except you are willing to search the set of all representations in a brute way (of course approximate zeros are meant).

For me the most simple functions are of polynomial type, univariate. And already for those it is more than non-trivial to have reliable and robust algorithm which works in variable precision, or just for usual double precision. But Maple can do it, I think that is based on Sturm's theorem. I would have to dig for citations or literature (not sure whether one first has to find all complex roots).

Now there are 2 obvious generalizations of polynomial, fractions of them (rationals, the quotient field) - for which it is clear from the above.

And (formal) power series and evaluating those in numbers and even if one restricts to 'the' elementary functions (covering those examples in the post) I would be astonished, if a practical algorithm exists (actually I do not even know whether one can prove such theoretical existence):

Certainly one first would have to decide whether there are only finitely many zeros (and the exact number) or more of them. Or none. Even if restricting to those function being analytic in the whole complex plane I see no reason why one should expect that (besides the condition 'real zero').

I doubt that something like the zero-counting integral will help in general. And Picard's theorem would not as well, because of numerical issues (say you find 'no zeros' numerical for a disturbed question and conclude 'then it takes any value' that may be false due to precision).

It simply is a wish, which is too optimistic beyond special cases (which Maple may do or is too weak).

 

region bounds

I was talking about possibly bounding the region where real zeroes lay. Finding all of them within that region is another story. And I am thinking about mixed symbolic-numeric techniques for a class of good enough functions (which may cover most cases in practice). E.g. those for which is provable that are larger than a constant A>0 for x>x0 say, and then using x0 as a right bound. For functions that diverge or have a nonzero limit for x->infinity, it sounds to me as something possible.

Intersection of y=x^2-10-10*sin(x) and y=2

This is sort of along the same line of problem. 

a:= y=x^2-10-10*sin(x);

b:=y=2;

solve({a,b},{x,y});

Again only returns one solution, x as a RootOf and y=2 answer.  Using allvalues(%) returns the same answer.  Can't get the other 3 points of intersection with a single command. 

gulliet's picture

Note that your system of

Note that your system of equation can be written as a single expression, which has four zeroes that can be found by Roots.

> expr := -12+x^2-10*sin(x);
                                   2            
                            -12 + x  - 10 sin(x)
> plot(expr);

97_fourzeroes.jpg

> Student[Calculus1]:-Roots(expr, x = -10 .. 10, numeric);
           [-4.690152208, -2.574460734, -1.442831640, 3.271613316]

Regards,
-- Jean-Marc

and if b:=cos(x)

Yes thanks.  Does that work the same if we change b:=cos(x) ?

gkokovidis's picture

and if b:=cos(x)

Using  Student[Calculus1]:-Roots(expr, x = -10 .. 10, numeric);  where expr is your new expression with b:=cos(x), you will get a diiferent set of answers.  So, to answer your question, yes it does.  Did you try it, and did it not work for you?  Below are the values that I got.

[-4.367042332, -3.390886872, -1.144307303, 3.088083981]

 

Regards,
Georgios Kokovidis
Dräger Medical


Sure

with(Student[Calculus1]):

c:=Roots(x^2-10-sin(x)-cos(x),x=-10..10,numeric);

But now I have to substitute those values into a to find the y intercept for each x (ie. subs(c[1],a); etc...) for all the intercepts.  I really don't want to have to do that. 

What I'd like to do is have Maple calculate the x,y intercepts in one step and show them to me.  This is what I've tried and I can't seem to prod it out of Maple. 

a:=y=x^2-10-10*sin(x);

b:=y=cos(x);

solve({a,b});  or solve({a,b},{x,y});

Returns x=RootOf ... and y=RootOf answers.  I try to evalf(%) or allvalues(%)  but I only get one answer

{x=-1.006881416,y=0.5344990470}

fsolve({a,b}); or fsolve({a,b},{s,y})   gives me another of the intercepts, but doesn't tell me all of them {x=-1.144307303,y=0.4136768823}  

fsolve doens't seem to like multiple equations specified over a range so I can't find all the intercepts using fsolve without having to first combine the equations and finding the roots and then use the subs command. 

So how can I get maple to produce the 4 points of intersection {x=..., y= ...} , {x= ... , y= ...} , {x= .. , y= ... } , {x= .. , y= ... } ?  

 

 

gulliet's picture

You could use *seq* or write a two-line (or so) procedure

as illustrated below:

> restart;
> f := x^2-10-10*sin(x);

                              2                 
                             x  - 10 - 10 sin(x)

> g := cos(x);
                                   cos(x)
> h := f-g;

                         2                          
                        x  - 10 - 10 sin(x) - cos(x)

> plot([f, g, h], x = -5 .. 5);

97_xyintercept.jpg

> Student[Calculus1]:-Roots(h, x = -10 .. 10, numeric);

           [-4.367042332, -3.390886872, -1.144307303, 3.088083981]

> [seq([x, f(x)], `in`(x, %))];

        [[-4.367042332, -0.338522877], [-3.390886872, -0.969086791], 
         [-1.144307303, 0.413676882], [3.088083981, -0.9985687470]]

> mySolve := proc (fun) local xs; 
        xs := Student[Calculus1]:-Roots(fun, x = -10 .. 10, numeric); 
        [seq([x, f(x)], `in`(x, xs))] 
    end proc;

> mySolve(f-g);
        [[-4.367042332, -0.338522877], [-3.390886872, -0.969086791], 
         [-1.144307303, 0.413676882], [3.088083981, -0.9985687470]]

> help("proc");

HTH,
-- Jean-Marc

gkokovidis's picture

Algorithm

The Application Center has a routine that might be useful to you for finding roots and displaying the x,y pairs.   Attached is a worksheet with your last function.  Based on the tolerance, your answers will match what you got from the Roots function in the Student Calculus package.  Download 221_roots.mws
View file details

 

Regards,
Georgios Kokovidis

Dräger Medical


 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
}