Statistiques
| Révision :

root / ase / optimize / fmin_bfgs.py @ 1

Historique | Voir | Annoter | Télécharger (15,47 ko)

1 1 tkerber
#__docformat__ = "restructuredtext en"
2 1 tkerber
# ******NOTICE***************
3 1 tkerber
# optimize.py module by Travis E. Oliphant
4 1 tkerber
#
5 1 tkerber
# You may copy and use this module as you see fit with no
6 1 tkerber
# guarantee implied provided you keep this notice in all copies.
7 1 tkerber
# *****END NOTICE************
8 1 tkerber
9 1 tkerber
import numpy
10 1 tkerber
from numpy import atleast_1d, eye, mgrid, argmin, zeros, shape, empty, \
11 1 tkerber
     squeeze, vectorize, asarray, absolute, sqrt, Inf, asfarray, isinf
12 1 tkerber
from ase.utils.linesearch import LineSearch
13 1 tkerber
14 1 tkerber
# These have been copied from Numeric's MLab.py
15 1 tkerber
# I don't think they made the transition to scipy_core
16 1 tkerber
17 1 tkerber
# Copied and modified from scipy_optimize
18 1 tkerber
abs = absolute
19 1 tkerber
import __builtin__
20 1 tkerber
pymin = __builtin__.min
21 1 tkerber
pymax = __builtin__.max
22 1 tkerber
__version__="0.7"
23 1 tkerber
_epsilon = sqrt(numpy.finfo(float).eps)
24 1 tkerber
25 1 tkerber
def fmin_bfgs(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf,
26 1 tkerber
              epsilon=_epsilon, maxiter=None, full_output=0, disp=1,
27 1 tkerber
              retall=0, callback=None, maxstep=0.2):
28 1 tkerber
    """Minimize a function using the BFGS algorithm.
29 1 tkerber

30 1 tkerber
    Parameters:
31 1 tkerber

32 1 tkerber
      f : callable f(x,*args)
33 1 tkerber
          Objective function to be minimized.
34 1 tkerber
      x0 : ndarray
35 1 tkerber
          Initial guess.
36 1 tkerber
      fprime : callable f'(x,*args)
37 1 tkerber
          Gradient of f.
38 1 tkerber
      args : tuple
39 1 tkerber
          Extra arguments passed to f and fprime.
40 1 tkerber
      gtol : float
41 1 tkerber
          Gradient norm must be less than gtol before succesful termination.
42 1 tkerber
      norm : float
43 1 tkerber
          Order of norm (Inf is max, -Inf is min)
44 1 tkerber
      epsilon : int or ndarray
45 1 tkerber
          If fprime is approximated, use this value for the step size.
46 1 tkerber
      callback : callable
47 1 tkerber
          An optional user-supplied function to call after each
48 1 tkerber
          iteration.  Called as callback(xk), where xk is the
49 1 tkerber
          current parameter vector.
50 1 tkerber

51 1 tkerber
    Returns: (xopt, {fopt, gopt, Hopt, func_calls, grad_calls, warnflag}, <allvecs>)
52 1 tkerber

53 1 tkerber
        xopt : ndarray
54 1 tkerber
            Parameters which minimize f, i.e. f(xopt) == fopt.
55 1 tkerber
        fopt : float
56 1 tkerber
            Minimum value.
57 1 tkerber
        gopt : ndarray
58 1 tkerber
            Value of gradient at minimum, f'(xopt), which should be near 0.
59 1 tkerber
        Bopt : ndarray
60 1 tkerber
            Value of 1/f''(xopt), i.e. the inverse hessian matrix.
61 1 tkerber
        func_calls : int
62 1 tkerber
            Number of function_calls made.
63 1 tkerber
        grad_calls : int
64 1 tkerber
            Number of gradient calls made.
65 1 tkerber
        warnflag : integer
66 1 tkerber
            1 : Maximum number of iterations exceeded.
67 1 tkerber
            2 : Gradient and/or function calls not changing.
68 1 tkerber
        allvecs  :  list
69 1 tkerber
            Results at each iteration.  Only returned if retall is True.
70 1 tkerber

71 1 tkerber
    *Other Parameters*:
72 1 tkerber
        maxiter : int
73 1 tkerber
            Maximum number of iterations to perform.
74 1 tkerber
        full_output : bool
75 1 tkerber
            If True,return fopt, func_calls, grad_calls, and warnflag
76 1 tkerber
            in addition to xopt.
77 1 tkerber
        disp : bool
78 1 tkerber
            Print convergence message if True.
79 1 tkerber
        retall : bool
80 1 tkerber
            Return a list of results at each iteration if True.
81 1 tkerber

82 1 tkerber
    Notes:
83 1 tkerber

84 1 tkerber
        Optimize the function, f, whose gradient is given by fprime
85 1 tkerber
        using the quasi-Newton method of Broyden, Fletcher, Goldfarb,
86 1 tkerber
        and Shanno (BFGS) See Wright, and Nocedal 'Numerical
87 1 tkerber
        Optimization', 1999, pg. 198.
88 1 tkerber

89 1 tkerber
    *See Also*:
90 1 tkerber

91 1 tkerber
      scikits.openopt : SciKit which offers a unified syntax to call
92 1 tkerber
                        this and other solvers.
93 1 tkerber

94 1 tkerber
    """
95 1 tkerber
    x0 = asarray(x0).squeeze()
96 1 tkerber
    if x0.ndim == 0:
97 1 tkerber
        x0.shape = (1,)
98 1 tkerber
    if maxiter is None:
99 1 tkerber
        maxiter = len(x0)*200
100 1 tkerber
    func_calls, f = wrap_function(f, args)
101 1 tkerber
    if fprime is None:
102 1 tkerber
        grad_calls, myfprime = wrap_function(approx_fprime, (f, epsilon))
103 1 tkerber
    else:
104 1 tkerber
        grad_calls, myfprime = wrap_function(fprime, args)
105 1 tkerber
    gfk = myfprime(x0)
106 1 tkerber
    k = 0
107 1 tkerber
    N = len(x0)
108 1 tkerber
    I = numpy.eye(N,dtype=int)
109 1 tkerber
    Hk = I
110 1 tkerber
    old_fval = f(x0)
111 1 tkerber
    old_old_fval = old_fval + 5000
112 1 tkerber
    xk = x0
113 1 tkerber
    if retall:
114 1 tkerber
        allvecs = [x0]
115 1 tkerber
    sk = [2*gtol]
116 1 tkerber
    warnflag = 0
117 1 tkerber
    gnorm = vecnorm(gfk,ord=norm)
118 1 tkerber
    while (gnorm > gtol) and (k < maxiter):
119 1 tkerber
        pk = -numpy.dot(Hk,gfk)
120 1 tkerber
        ls = LineSearch()
121 1 tkerber
        alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
122 1 tkerber
           ls._line_search(f,myfprime,xk,pk,gfk,
123 1 tkerber
                                  old_fval,old_old_fval,maxstep=maxstep)
124 1 tkerber
        if alpha_k is None:  # line search failed try different one.
125 1 tkerber
            alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
126 1 tkerber
                     line_search(f,myfprime,xk,pk,gfk,
127 1 tkerber
                                 old_fval,old_old_fval)
128 1 tkerber
            if alpha_k is None:
129 1 tkerber
                # This line search also failed to find a better solution.
130 1 tkerber
                warnflag = 2
131 1 tkerber
                break
132 1 tkerber
        xkp1 = xk + alpha_k * pk
133 1 tkerber
        if retall:
134 1 tkerber
            allvecs.append(xkp1)
135 1 tkerber
        sk = xkp1 - xk
136 1 tkerber
        xk = xkp1
137 1 tkerber
        if gfkp1 is None:
138 1 tkerber
            gfkp1 = myfprime(xkp1)
139 1 tkerber
140 1 tkerber
        yk = gfkp1 - gfk
141 1 tkerber
        gfk = gfkp1
142 1 tkerber
        if callback is not None:
143 1 tkerber
            callback(xk)
144 1 tkerber
        k += 1
145 1 tkerber
        gnorm = vecnorm(gfk,ord=norm)
146 1 tkerber
        if (gnorm <= gtol):
147 1 tkerber
            break
148 1 tkerber
149 1 tkerber
        try: # this was handled in numeric, let it remaines for more safety
150 1 tkerber
            rhok = 1.0 / (numpy.dot(yk,sk))
151 1 tkerber
        except ZeroDivisionError:
152 1 tkerber
            rhok = 1000.0
153 1 tkerber
            print "Divide-by-zero encountered: rhok assumed large"
154 1 tkerber
        if isinf(rhok): # this is patch for numpy
155 1 tkerber
            rhok = 1000.0
156 1 tkerber
            print "Divide-by-zero encountered: rhok assumed large"
157 1 tkerber
        A1 = I - sk[:,numpy.newaxis] * yk[numpy.newaxis,:] * rhok
158 1 tkerber
        A2 = I - yk[:,numpy.newaxis] * sk[numpy.newaxis,:] * rhok
159 1 tkerber
        Hk = numpy.dot(A1,numpy.dot(Hk,A2)) + rhok * sk[:,numpy.newaxis] \
160 1 tkerber
                 * sk[numpy.newaxis,:]
161 1 tkerber
162 1 tkerber
    if disp or full_output:
163 1 tkerber
        fval = old_fval
164 1 tkerber
    if warnflag == 2:
165 1 tkerber
        if disp:
166 1 tkerber
            print "Warning: Desired error not necessarily achieved" \
167 1 tkerber
                  "due to precision loss"
168 1 tkerber
            print "         Current function value: %f" % fval
169 1 tkerber
            print "         Iterations: %d" % k
170 1 tkerber
            print "         Function evaluations: %d" % func_calls[0]
171 1 tkerber
            print "         Gradient evaluations: %d" % grad_calls[0]
172 1 tkerber
173 1 tkerber
    elif k >= maxiter:
174 1 tkerber
        warnflag = 1
175 1 tkerber
        if disp:
176 1 tkerber
            print "Warning: Maximum number of iterations has been exceeded"
177 1 tkerber
            print "         Current function value: %f" % fval
178 1 tkerber
            print "         Iterations: %d" % k
179 1 tkerber
            print "         Function evaluations: %d" % func_calls[0]
180 1 tkerber
            print "         Gradient evaluations: %d" % grad_calls[0]
181 1 tkerber
    else:
182 1 tkerber
        if disp:
183 1 tkerber
            print "Optimization terminated successfully."
184 1 tkerber
            print "         Current function value: %f" % fval
185 1 tkerber
            print "         Iterations: %d" % k
186 1 tkerber
            print "         Function evaluations: %d" % func_calls[0]
187 1 tkerber
            print "         Gradient evaluations: %d" % grad_calls[0]
188 1 tkerber
189 1 tkerber
    if full_output:
190 1 tkerber
        retlist = xk, fval, gfk, Hk, func_calls[0], grad_calls[0], warnflag
191 1 tkerber
        if retall:
192 1 tkerber
            retlist += (allvecs,)
193 1 tkerber
    else:
194 1 tkerber
        retlist = xk
195 1 tkerber
        if retall:
196 1 tkerber
            retlist = (xk, allvecs)
197 1 tkerber
198 1 tkerber
    return retlist
199 1 tkerber
200 1 tkerber
def vecnorm(x, ord=2):
201 1 tkerber
    if ord == Inf:
202 1 tkerber
        return numpy.amax(abs(x))
203 1 tkerber
    elif ord == -Inf:
204 1 tkerber
        return numpy.amin(abs(x))
205 1 tkerber
    else:
206 1 tkerber
        return numpy.sum(abs(x)**ord,axis=0)**(1.0/ord)
207 1 tkerber
208 1 tkerber
def wrap_function(function, args):
209 1 tkerber
    ncalls = [0]
210 1 tkerber
    def function_wrapper(x):
211 1 tkerber
        ncalls[0] += 1
212 1 tkerber
        return function(x, *args)
213 1 tkerber
    return ncalls, function_wrapper
214 1 tkerber
215 1 tkerber
def _cubicmin(a,fa,fpa,b,fb,c,fc):
216 1 tkerber
    # finds the minimizer for a cubic polynomial that goes through the
217 1 tkerber
    #  points (a,fa), (b,fb), and (c,fc) with derivative at a of fpa.
218 1 tkerber
    #
219 1 tkerber
    # if no minimizer can be found return None
220 1 tkerber
    #
221 1 tkerber
    # f(x) = A *(x-a)^3 + B*(x-a)^2 + C*(x-a) + D
222 1 tkerber
223 1 tkerber
    C = fpa
224 1 tkerber
    D = fa
225 1 tkerber
    db = b-a
226 1 tkerber
    dc = c-a
227 1 tkerber
    if (db == 0) or (dc == 0) or (b==c): return None
228 1 tkerber
    denom = (db*dc)**2 * (db-dc)
229 1 tkerber
    d1 = empty((2,2))
230 1 tkerber
    d1[0,0] = dc**2
231 1 tkerber
    d1[0,1] = -db**2
232 1 tkerber
    d1[1,0] = -dc**3
233 1 tkerber
    d1[1,1] = db**3
234 1 tkerber
    [A,B] = numpy.dot(d1,asarray([fb-fa-C*db,fc-fa-C*dc]).flatten())
235 1 tkerber
    A /= denom
236 1 tkerber
    B /= denom
237 1 tkerber
    radical = B*B-3*A*C
238 1 tkerber
    if radical < 0:  return None
239 1 tkerber
    if (A == 0): return None
240 1 tkerber
    xmin = a + (-B + sqrt(radical))/(3*A)
241 1 tkerber
    return xmin
242 1 tkerber
243 1 tkerber
def _quadmin(a,fa,fpa,b,fb):
244 1 tkerber
    # finds the minimizer for a quadratic polynomial that goes through
245 1 tkerber
    #  the points (a,fa), (b,fb) with derivative at a of fpa
246 1 tkerber
    # f(x) = B*(x-a)^2 + C*(x-a) + D
247 1 tkerber
    D = fa
248 1 tkerber
    C = fpa
249 1 tkerber
    db = b-a*1.0
250 1 tkerber
    if (db==0): return None
251 1 tkerber
    B = (fb-D-C*db)/(db*db)
252 1 tkerber
    if (B <= 0): return None
253 1 tkerber
    xmin = a  - C / (2.0*B)
254 1 tkerber
    return xmin
255 1 tkerber
256 1 tkerber
def zoom(a_lo, a_hi, phi_lo, phi_hi, derphi_lo,
257 1 tkerber
         phi, derphi, phi0, derphi0, c1, c2):
258 1 tkerber
    maxiter = 10
259 1 tkerber
    i = 0
260 1 tkerber
    delta1 = 0.2  # cubic interpolant check
261 1 tkerber
    delta2 = 0.1  # quadratic interpolant check
262 1 tkerber
    phi_rec = phi0
263 1 tkerber
    a_rec = 0
264 1 tkerber
    while 1:
265 1 tkerber
        # interpolate to find a trial step length between a_lo and a_hi
266 1 tkerber
        # Need to choose interpolation here.  Use cubic interpolation and then if the
267 1 tkerber
        #  result is within delta * dalpha or outside of the interval bounded by a_lo or a_hi
268 1 tkerber
        #  then use quadratic interpolation, if the result is still too close, then use bisection
269 1 tkerber
270 1 tkerber
        dalpha = a_hi-a_lo;
271 1 tkerber
        if dalpha < 0: a,b = a_hi,a_lo
272 1 tkerber
        else: a,b = a_lo, a_hi
273 1 tkerber
274 1 tkerber
        # minimizer of cubic interpolant
275 1 tkerber
        #    (uses phi_lo, derphi_lo, phi_hi, and the most recent value of phi)
276 1 tkerber
        #      if the result is too close to the end points (or out of the interval)
277 1 tkerber
        #         then use quadratic interpolation with phi_lo, derphi_lo and phi_hi
278 1 tkerber
        #      if the result is stil too close to the end points (or out of the interval)
279 1 tkerber
        #         then use bisection
280 1 tkerber
281 1 tkerber
        if (i > 0):
282 1 tkerber
            cchk = delta1*dalpha
283 1 tkerber
            a_j = _cubicmin(a_lo, phi_lo, derphi_lo, a_hi, phi_hi, a_rec, phi_rec)
284 1 tkerber
        if (i==0) or (a_j is None) or (a_j > b-cchk) or (a_j < a+cchk):
285 1 tkerber
            qchk = delta2*dalpha
286 1 tkerber
            a_j = _quadmin(a_lo, phi_lo, derphi_lo, a_hi, phi_hi)
287 1 tkerber
            if (a_j is None) or (a_j > b-qchk) or (a_j < a+qchk):
288 1 tkerber
                a_j = a_lo + 0.5*dalpha
289 1 tkerber
#                print "Using bisection."
290 1 tkerber
#            else: print "Using quadratic."
291 1 tkerber
#        else: print "Using cubic."
292 1 tkerber
293 1 tkerber
        # Check new value of a_j
294 1 tkerber
295 1 tkerber
        phi_aj = phi(a_j)
296 1 tkerber
        if (phi_aj > phi0 + c1*a_j*derphi0) or (phi_aj >= phi_lo):
297 1 tkerber
            phi_rec = phi_hi
298 1 tkerber
            a_rec = a_hi
299 1 tkerber
            a_hi = a_j
300 1 tkerber
            phi_hi = phi_aj
301 1 tkerber
        else:
302 1 tkerber
            derphi_aj = derphi(a_j)
303 1 tkerber
            if abs(derphi_aj) <= -c2*derphi0:
304 1 tkerber
                a_star = a_j
305 1 tkerber
                val_star = phi_aj
306 1 tkerber
                valprime_star = derphi_aj
307 1 tkerber
                break
308 1 tkerber
            if derphi_aj*(a_hi - a_lo) >= 0:
309 1 tkerber
                phi_rec = phi_hi
310 1 tkerber
                a_rec = a_hi
311 1 tkerber
                a_hi = a_lo
312 1 tkerber
                phi_hi = phi_lo
313 1 tkerber
            else:
314 1 tkerber
                phi_rec = phi_lo
315 1 tkerber
                a_rec = a_lo
316 1 tkerber
            a_lo = a_j
317 1 tkerber
            phi_lo = phi_aj
318 1 tkerber
            derphi_lo = derphi_aj
319 1 tkerber
        i += 1
320 1 tkerber
        if (i > maxiter):
321 1 tkerber
            a_star = a_j
322 1 tkerber
            val_star = phi_aj
323 1 tkerber
            valprime_star = None
324 1 tkerber
            break
325 1 tkerber
    return a_star, val_star, valprime_star
326 1 tkerber
327 1 tkerber
def line_search(f, myfprime, xk, pk, gfk, old_fval, old_old_fval,
328 1 tkerber
                args=(), c1=1e-4, c2=0.9, amax=50):
329 1 tkerber
    """Find alpha that satisfies strong Wolfe conditions.
330 1 tkerber

331 1 tkerber
    Parameters:
332 1 tkerber

333 1 tkerber
        f : callable f(x,*args)
334 1 tkerber
            Objective function.
335 1 tkerber
        myfprime : callable f'(x,*args)
336 1 tkerber
            Objective function gradient (can be None).
337 1 tkerber
        xk : ndarray
338 1 tkerber
            Starting point.
339 1 tkerber
        pk : ndarray
340 1 tkerber
            Search direction.
341 1 tkerber
        gfk : ndarray
342 1 tkerber
            Gradient value for x=xk (xk being the current parameter
343 1 tkerber
            estimate).
344 1 tkerber
        args : tuple
345 1 tkerber
            Additional arguments passed to objective function.
346 1 tkerber
        c1 : float
347 1 tkerber
            Parameter for Armijo condition rule.
348 1 tkerber
        c2 : float
349 1 tkerber
            Parameter for curvature condition rule.
350 1 tkerber

351 1 tkerber
    Returns:
352 1 tkerber

353 1 tkerber
        alpha0 : float
354 1 tkerber
            Alpha for which ``x_new = x0 + alpha * pk``.
355 1 tkerber
        fc : int
356 1 tkerber
            Number of function evaluations made.
357 1 tkerber
        gc : int
358 1 tkerber
            Number of gradient evaluations made.
359 1 tkerber

360 1 tkerber
    Notes:
361 1 tkerber

362 1 tkerber
        Uses the line search algorithm to enforce strong Wolfe
363 1 tkerber
        conditions.  See Wright and Nocedal, 'Numerical Optimization',
364 1 tkerber
        1999, pg. 59-60.
365 1 tkerber

366 1 tkerber
        For the zoom phase it uses an algorithm by [...].
367 1 tkerber

368 1 tkerber
    """
369 1 tkerber
370 1 tkerber
    global _ls_fc, _ls_gc, _ls_ingfk
371 1 tkerber
    _ls_fc = 0
372 1 tkerber
    _ls_gc = 0
373 1 tkerber
    _ls_ingfk = None
374 1 tkerber
    def phi(alpha):
375 1 tkerber
        global _ls_fc
376 1 tkerber
        _ls_fc += 1
377 1 tkerber
        return f(xk+alpha*pk,*args)
378 1 tkerber
379 1 tkerber
    if isinstance(myfprime,type(())):
380 1 tkerber
        def phiprime(alpha):
381 1 tkerber
            global _ls_fc, _ls_ingfk
382 1 tkerber
            _ls_fc += len(xk)+1
383 1 tkerber
            eps = myfprime[1]
384 1 tkerber
            fprime = myfprime[0]
385 1 tkerber
            newargs = (f,eps) + args
386 1 tkerber
            _ls_ingfk = fprime(xk+alpha*pk,*newargs)  # store for later use
387 1 tkerber
            return numpy.dot(_ls_ingfk,pk)
388 1 tkerber
    else:
389 1 tkerber
        fprime = myfprime
390 1 tkerber
        def phiprime(alpha):
391 1 tkerber
            global _ls_gc, _ls_ingfk
392 1 tkerber
            _ls_gc += 1
393 1 tkerber
            _ls_ingfk = fprime(xk+alpha*pk,*args)  # store for later use
394 1 tkerber
            return numpy.dot(_ls_ingfk,pk)
395 1 tkerber
396 1 tkerber
    alpha0 = 0
397 1 tkerber
    phi0 = old_fval
398 1 tkerber
    derphi0 = numpy.dot(gfk,pk)
399 1 tkerber
400 1 tkerber
    alpha1 = pymin(1.0,1.01*2*(phi0-old_old_fval)/derphi0)
401 1 tkerber
402 1 tkerber
    if alpha1 == 0:
403 1 tkerber
        # This shouldn't happen. Perhaps the increment has slipped below
404 1 tkerber
        # machine precision?  For now, set the return variables skip the
405 1 tkerber
        # useless while loop, and raise warnflag=2 due to possible imprecision.
406 1 tkerber
        alpha_star = None
407 1 tkerber
        fval_star = old_fval
408 1 tkerber
        old_fval = old_old_fval
409 1 tkerber
        fprime_star = None
410 1 tkerber
411 1 tkerber
    phi_a1 = phi(alpha1)
412 1 tkerber
    #derphi_a1 = phiprime(alpha1)  evaluated below
413 1 tkerber
414 1 tkerber
    phi_a0 = phi0
415 1 tkerber
    derphi_a0 = derphi0
416 1 tkerber
417 1 tkerber
    i = 1
418 1 tkerber
    maxiter = 10
419 1 tkerber
    while 1:         # bracketing phase
420 1 tkerber
        if alpha1 == 0:
421 1 tkerber
            break
422 1 tkerber
        if (phi_a1 > phi0 + c1*alpha1*derphi0) or \
423 1 tkerber
           ((phi_a1 >= phi_a0) and (i > 1)):
424 1 tkerber
            alpha_star, fval_star, fprime_star = \
425 1 tkerber
                        zoom(alpha0, alpha1, phi_a0,
426 1 tkerber
                             phi_a1, derphi_a0, phi, phiprime,
427 1 tkerber
                             phi0, derphi0, c1, c2)
428 1 tkerber
            break
429 1 tkerber
430 1 tkerber
        derphi_a1 = phiprime(alpha1)
431 1 tkerber
        if (abs(derphi_a1) <= -c2*derphi0):
432 1 tkerber
            alpha_star = alpha1
433 1 tkerber
            fval_star = phi_a1
434 1 tkerber
            fprime_star = derphi_a1
435 1 tkerber
            break
436 1 tkerber
437 1 tkerber
        if (derphi_a1 >= 0):
438 1 tkerber
            alpha_star, fval_star, fprime_star = \
439 1 tkerber
                        zoom(alpha1, alpha0, phi_a1,
440 1 tkerber
                             phi_a0, derphi_a1, phi, phiprime,
441 1 tkerber
                             phi0, derphi0, c1, c2)
442 1 tkerber
            break
443 1 tkerber
444 1 tkerber
        alpha2 = 2 * alpha1   # increase by factor of two on each iteration
445 1 tkerber
        i = i + 1
446 1 tkerber
        alpha0 = alpha1
447 1 tkerber
        alpha1 = alpha2
448 1 tkerber
        phi_a0 = phi_a1
449 1 tkerber
        phi_a1 = phi(alpha1)
450 1 tkerber
        derphi_a0 = derphi_a1
451 1 tkerber
452 1 tkerber
        # stopping test if lower function not found
453 1 tkerber
        if (i > maxiter):
454 1 tkerber
            alpha_star = alpha1
455 1 tkerber
            fval_star = phi_a1
456 1 tkerber
            fprime_star = None
457 1 tkerber
            break
458 1 tkerber
459 1 tkerber
    if fprime_star is not None:
460 1 tkerber
        # fprime_star is a number (derphi) -- so use the most recently
461 1 tkerber
        # calculated gradient used in computing it derphi = gfk*pk
462 1 tkerber
        # this is the gradient at the next step no need to compute it
463 1 tkerber
        # again in the outer loop.
464 1 tkerber
        fprime_star = _ls_ingfk
465 1 tkerber
466 1 tkerber
    return alpha_star, _ls_fc, _ls_gc, fval_star, old_fval, fprime_star
467 1 tkerber
468 1 tkerber
def approx_fprime(xk,f,epsilon,*args):
469 1 tkerber
    f0 = f(*((xk,)+args))
470 1 tkerber
    grad = numpy.zeros((len(xk),), float)
471 1 tkerber
    ei = numpy.zeros((len(xk),), float)
472 1 tkerber
    for k in range(len(xk)):
473 1 tkerber
        ei[k] = epsilon
474 1 tkerber
        grad[k] = (f(*((xk+ei,)+args)) - f0)/epsilon
475 1 tkerber
        ei[k] = 0.0
476 1 tkerber
    return grad