Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#3980 closed defect (fixed)

[with patch, positive review] Find_root bug

Reported by: kcrisman Owned by: jwmerrill
Priority: minor Milestone: sage-3.1.3
Component: calculus Keywords:
Cc: Merged in:
Authors: Reviewers:
Report Upstream: Work issues:
Branch: Commit:
Dependencies: Stopgaps:

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.

Attachments (1)

3980.patch (2.9 KB) - added by jwmerrill 6 years ago.

Download all attachments as: .zip

Change History (10)

comment:1 Changed 6 years ago by jwmerrill

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

comment:2 Changed 6 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 6 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 6 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 6 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

Changed 6 years ago by jwmerrill

comment:6 Changed 6 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 6 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 6 years ago by mabshoff

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

Merged in Sage 3.1.3.alpha3.

comment:9 Changed 6 years ago by mabshoff

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