# Revision history [back]

I suppose this is not homework. If it is, you'd better try to solve it yourself, peeking this answer only for confirmation, unless you want to miss the point of the homework.

The difficulty isn't to find one solution, but to find them all. In some cases, solve might be able to give them an explicit form. Not here.

find_root will give you one real root in this interval if such one exists. To find the others, you might try searching them in the subintervals defined by this root (with a slight restriction to avoid finding the same root repetitively). However, such a recursive computation should be limited in avoid to (try to) return an infinite number of solutions. Hence the proposal :

def find_roots(f, a, b, depth=10, epsilon=1e-10):
def find1(f, a, b, **kwdargs):
try:
r =find_root(f, a, b)
return r
except RuntimeError:
return None
if a > b: a, b = b, a
r = find1(f, a, b)
if r is None: return set([])
if depth == 0 : return set([r])
a1 = a + (r - a) * epsilon
b1 = r - (r - a) * epsilon
a2 = r + (b - r) * epsilon
b2 = b - (b - r) * epsilon
R1 = find_roots(f, a1, b1, depth=depth-1, epsilon=epsilon)
R2 = find_roots(f, a2, b2, depth=depth-1, epsilon=epsilon)
return set([r]).union(R1).union(R2)

[ Handling and passing the optional arguments to find_root is left as an exercise to the reader...]

Sol=find_roots((x^2*cos(2*x)).diff(x,2),-10,10) ; Sol
{-8.75241852237047,
-7.205215809879128,
-5.66982003470027,
-4.156992355472504,
-2.692864827014006,
-1.3444837495903466,
-0.299870710513912,
0.299870710513912,
1.3444837495903472,
2.692864827014006,
4.156992355472463,
5.669820034700045,
7.205215809879129,
8.752418522370563}

This proposal of fourteen roots is consistent with the graphical representation :

sage: (x^2*cos(2*x)).diff(x,2).plot((-10,10), ymin=-5, ymax=5)

However, if this answer is numerically satisfying, it is not a proof, which should be searched by other (formal) means.

The depth parameter has effects varying as a function of the implementation of find_root, which does not explicitly documents its algorithm. FWIW, the default depth=10 allows find_roots to return 63 of the (countable) infinity of roots of $\sin{\frac{1}{x}}$ between 0 and 1:

sage: len(find_roots(sin(1/x),0,1))
63

HTH,