Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

BUG: optimize: fix epsfcn choice in minpack routines

An additional sqrt() was introduced in 703dc23 --- minpack takes the
sqrt internally, so it should not be done again.

The routines can still fail if the problem is badly scaled. The test is
here changed to be less badly scaled.  The correct choice of epsfcn is
problem-dependent and in general needs to be left to the user.

Fixes gh-2639
  • Loading branch information...
commit c77b991c95cd655644cc7ef990c7dd075b162553 1 parent 7b0ac22
@pv pv authored
Showing with 23 additions and 4 deletions.
  1. +3 −3 scipy/optimize/minpack.py
  2. +20 −1 scipy/optimize/tests/test_minpack.py
View
6 scipy/optimize/minpack.py
@@ -6,7 +6,7 @@
from numpy import (atleast_1d, dot, take, triu, shape, eye,
transpose, zeros, product, greater, array,
all, where, isscalar, asarray, inf, abs,
- finfo, inexact, issubdtype, dtype, sqrt)
+ finfo, inexact, issubdtype, dtype)
from .optimize import Result, _check_unknown_options
error = _minpack.error
@@ -195,7 +195,7 @@ def _root_hybr(func, x0, args=(), jac=None,
args = (args,)
shape, dtype = _check_func('fsolve', 'func', func, x0, args, n, (n,))
if epsfcn is None:
- epsfcn = sqrt(finfo(dtype).eps)
+ epsfcn = finfo(dtype).eps
Dfun = jac
if Dfun is None:
if band is None:
@@ -370,7 +370,7 @@ def leastsq(func, x0, args=(), Dfun=None, full_output=0,
if n > m:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
if epsfcn is None:
- epsfcn = sqrt(finfo(dtype).eps)
+ epsfcn = finfo(dtype).eps
if Dfun is None:
if maxfev == 0:
maxfev = 200*(n + 1)
View
21 scipy/optimize/tests/test_minpack.py
@@ -143,7 +143,7 @@ def test_wrong_shape_fprime_function(self):
assert_raises(TypeError, optimize.fsolve, func, x0=[0,1], fprime=deriv_func)
def test_float32(self):
- func = lambda x: np.array([x[0] - 1000, x[1] - 10000], dtype=np.float32)**2
+ func = lambda x: np.array([x[0] - 100, x[1] - 1000], dtype=np.float32)**2
p = optimize.fsolve(func, np.array([1, 1], np.float32))
assert_allclose(func(p), [0, 0], atol=1e-3)
@@ -317,6 +317,25 @@ def func(self, x, a, b):
assert_array_almost_equal(pcov, [[0.0852, -0.1260], [-0.1260, 0.1912]],
decimal=4)
+ def test_regression_2639(self):
+ # This test fails if epsfcn in leastsq is too large.
+ x = [574.14200000000005, 574.154, 574.16499999999996,
+ 574.17700000000002, 574.18799999999999, 574.19899999999996,
+ 574.21100000000001, 574.22199999999998, 574.23400000000004,
+ 574.245]
+ y = [859.0, 997.0, 1699.0, 2604.0, 2013.0, 1964.0, 2435.0,
+ 1550.0, 949.0, 841.0]
+ guess = [574.1861428571428, 574.2155714285715, 1302.0, 1302.0,
+ 0.0035019999999983615, 859.0]
+ good = [ 5.74177150e+02, 5.74209188e+02, 1.74187044e+03, 1.58646166e+03,
+ 1.0068462e-02, 8.57450661e+02]
+
+ def f_double_gauss(x, x0, x1, A0, A1, sigma, c):
+ return (A0*np.exp(-(x-x0)**2/(2.*sigma**2))
+ + A1*np.exp(-(x-x1)**2/(2.*sigma**2)) + c)
+ popt, pcov = curve_fit(f_double_gauss, x, y, guess, maxfev=10000)
+ assert_allclose(popt, good, rtol=1e-5)
+
class TestFixedPoint(TestCase):
Please sign in to comment.
Something went wrong with that request. Please try again.