# scipy/scipy

BUG: make sure fmin_bfgs doesn't get stuck in infinite loop. Closes #…

`…1494.`
1 parent bb4c46f commit a31acbf966f50665997d1fd1ced41d3a8b3e4187 rgommers committed Aug 15, 2011
Showing with 24 additions and 5 deletions.
1. +11 −5 scipy/optimize/optimize.py
2. +13 −0 scipy/optimize/tests/test_optimize.py
 @@ -559,6 +559,12 @@ def fmin_bfgs(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf, if (gnorm <= gtol): break + if not numpy.isfinite(old_fval): + # We correctly found +-Inf as optimal value, or something went + # wrong. + warnflag = 2 + break + try: # this was handled in numeric, let it remaines for more safety rhok = 1.0 / (numpy.dot(yk,sk)) except ZeroDivisionError: @@ -1563,11 +1569,11 @@ def fmin_powell(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None, The technical conditions for replacing the direction of greatest increase amount to checking that - 1. No further gain can be made along the - direction of greatest increase from that iteration - 2.The direction of greatest increase accounted for a large sufficient - fraction of the decrease in the function value from that - iteration of the inner loop. + 1. No further gain can be made along the direction of greatest increase + from that iteration. + 2. The direction of greatest increase accounted for a large sufficient + fraction of the decrease in the function value from that iteration of + the inner loop. References
 @@ -105,6 +105,19 @@ def test_bfgs(self): atol=1e-14, rtol=1e-7), self.trace[6:8]) + def test_bfgs_infinite(self): + """Test corner case where -Inf is the minimum. See #1494.""" + func = lambda x: -np.e**-x + fprime = lambda x: -func(x) + x0 = [0] + olderr = np.seterr(over='ignore') + try: + x = optimize.fmin_bfgs(func, x0, fprime, disp=False) + assert_(not np.isfinite(func(x))) + finally: + np.seterr(**olderr) + + def test_powell(self): """ Powell (direction set) optimization routine """

Contributor

### johannct commented on `a31acbf`Oct 24, 2011

 this code seems to fix the occurrence of infinites. In the case of a nan returned value, the problem is different in the sense that the linesearch_wolfe1 internal loop within the "while 1" statement never exits. Looks like we need something like this patch : diff --git a/scipy/optimize/linesearch.py b/scipy/optimize/linesearch.py index 02e9375..f858744 100644 --- a/scipy/optimize/linesearch.py +++ b/scipy/optimize/linesearch.py @@ -145,7 +145,10 @@ def scalar_search_wolfe1(phi, derphi, phi0=None, old_phi0=None, derphi0=None, stp, phi1, derphi1, task = minpack2.dcsrch(alpha1, phi1, derphi1, c1, c2, xtol, task, amin, amax, isave, dsave) `````` if task[:2] == asbytes('FG'): `````` `````` if np.isnan(phi1): `````` `````` task[:5] == asbytes('ERROR') `````` `````` break `````` `````` if task[:2] == asbytes('FG'): `````` alpha1 = stp phi1 = phi(stp) derphi1 = derphi(stp)