Opened 7 years ago

Closed 7 years ago

# [with patch, positive review] Find_root bug

Reported by: Owned by: kcrisman jwmerrill minor sage-3.1.3 calculus

### Description

The reciprocal of tangent is not a constant function, but Sage says otherwise.

```sage: z=tan
sage: z
tan
sage: 1/z
1/tan
sage: find_root(1/z,1,2)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)

<snip>

/Applications/sage/local/lib/python2.5/site-packages/sage/numerical/optimize.py in find_root(f, a, b, xtol, rtol, maxiter, full_output)
52     """
53     try:
---> 54         return f.find_root(a=a,b=b,xtol=xtol,rtol=rtol,maxiter=maxiter,full_output=full_output)
55     except AttributeError:
56         pass

/Applications/sage/local/lib/python2.5/site-packages/sage/calculus/calculus.py in find_root(self, a, b, var, xtol, rtol, maxiter, full_output)
3088                     return a
3089                 else:
-> 3090                     raise RuntimeError, "no zero in the interval, since constant expression is not 0."
3091             var = repr(w[0])
3092

RuntimeError: no zero in the interval, since constant expression is not 0.
```

### comment:1 Changed 7 years ago by jwmerrill

• Component changed from numerical to calculus
• Owner changed from jkantor to burcin

### comment:2 Changed 7 years ago by anakha

I have a less obscure example of this.

```sage: find_root(sin, -1, 1)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)

/Volumes/Place/anakha/sage-3.1.2.alpha4/<ipython console> in <module>()

/Volumes/Place/anakha/sage-3.1.2.alpha4/local/lib/python2.5/site-packages/sage/numerical/optimize.py in find_root(f, a, b, xtol, rtol, maxiter, full_output)
52     """
53     try:
---> 54         return f.find_root(a=a,b=b,xtol=xtol,rtol=rtol,maxiter=maxiter,full_output=full_output)
55     except AttributeError:
56         pass

/Volumes/Place/anakha/sage-3.1.2.alpha4/local/lib/python2.5/site-packages/sage/calculus/calculus.py in find_root(self, a, b, var, xtol, rtol, maxiter, full_output)
3120                     return a
3121                 else:
-> 3122                     raise RuntimeError, "no zero in the interval, since constant expression is not 0."
3123             var = repr(w[0])
3124

RuntimeError: no zero in the interval, since constant expression is not 0.
```

And I have traced down the bug to this:

```sage: sin.variables()
()
sage: (1/tan).variables()
()
```

Since these expressions contain no variables they are deemed constant and since they are not equal to 0 they have no roots. You can fix your example by trying:

```sage: find_root(1/tan(x), 1, 2)
1.5707963267948968
```

Also note that this works:

```sage: (1/tan)(1)
1/tan(1)
```

Although, technically no variables are there to be replaced.

I don't know if this is really a bug or not, or how to fix it.

### comment:3 Changed 7 years ago by jwmerrill

The problem is that find_root is asking the wrong question of its first argument. It asks "what are your variables?" Instead, it should ask "do you return a number when called with one argument?" I will try to code this up when I get a chance.

### comment:4 Changed 7 years ago by jwmerrill

• Owner changed from burcin to jwmerrill
• Summary changed from Find_root bug to [with patch, needs review] Find_root bug

Here's a patch that avoids asking the function what it's variables are.

### comment:5 Changed 7 years ago by mhampton

• Summary changed from [with patch, needs review] Find_root bug to [with patch, needs work] Find_root bug

Somehow this is now too permissive, since the following should return an error:

```sage: var('t')
sage: find_root(1/t-x,0,2)
1.0000000000005
```

### comment:6 Changed 7 years ago by jwmerrill

• Summary changed from [with patch, needs work] Find_root bug to [with patch, needs review] Find_root bug

Good catch mhampton. I modified the patch to throw a NotImplementedError? if self.number_of_variables() is greater than 1. This is closer to the old behavior. I added a new test to explicitly check the case you gave above.

### comment:7 Changed 7 years ago by mhampton

• Summary changed from [with patch, needs review] Find_root bug to [with patch, positive review] Find_root bug

OK, this passes tests and it seems OK. One thing I noticed, which I think can be considered beyond the scope of this patch, is that

```var('t')
plot(sin(t*x),-1,1)
```

quickly fails with "ValueError?: free variable: x", which is good, but:

```plot(lambda t: sin(t*x),-1,1)
```

tries to plot 400 values and finally gives

```verbose 0 (3585: plot.py, _plot) WARNING: When plotting, failed to evaluate function at 400 points.
verbose 0 (3585: plot.py, _plot) Last error message: 'float() argument must be a string or a number'
```

and an empty plot. It would be nice to speed up that failure if you know an easy way.

### comment:8 Changed 7 years ago by mabshoff

• Resolution set to fixed
• Status changed from new to closed

Merged in Sage 3.1.3.alpha3.

### comment:9 Changed 7 years ago by mabshoff

• Milestone changed from sage-3.2 to sage-3.1.3
Note: See TracTickets for help on using tickets.