~ubuntu-branches/ubuntu/raring/python-scipy/raring-proposed

« back to all changes in this revision

Viewing changes to Lib/optimize/optimize.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-01-07 14:12:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070107141212-mm0ebkh5b37hcpzn
* Remove build dependency on python-numpy-dev.
* python-scipy: Depend on python-numpy instead of python-numpy-dev.
* Package builds on other archs than i386. Closes: #402783.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from __future__ import nested_scopes
 
1
 
2
2
# ******NOTICE***************
3
3
# optimize.py module by Travis E. Oliphant
4
4
#
14
14
#  Updated strong Wolfe conditions line search to use cubic-interpolation (Mar. 2004)
15
15
 
16
16
# Minimization routines
17
 
"""optimize.py
18
 
 
19
 
A collection of general-purpose optimization routines using Numeric
20
 
 
21
 
 
22
 
N-D Algorithms
23
 
===============
24
 
fmin        ---      Nelder-Mead Simplex algorithm (uses only function calls).
25
 
fmin_powell ---      Powell (direction set) method (uses only function calls).
26
 
fmin_cg     ---      Non-linear (Polak-Rubiere) conjugate gradient algorithm
27
 
                       (can use function and gradient).
28
 
fmin_bfgs   ---      Quasi-Newton method (Broyden-Fletcher-Goldfarb-Shanno
29
 
                       (can use function and gradient).
30
 
fmin_ncg    ---      Line-search Newton Conjugate Gradient (can use function, 
31
 
                       gradient and hessian).
32
 
                     
33
 
 
34
 
brute       ---      Perform a brute force search for the minimum
35
 
                       with final optimization if desired.
36
 
 
37
 
1-D Algorithms
38
 
===============
39
 
brent       ---      Use Brent's method (does not need inital guess)
40
 
fminbound   ---      Bounded minimization for scalar functions on an
41
 
                     interval using Brent's parabolic/golden_mean method.
42
 
golden      --       Use Golden Section method (does not need initial guess)
43
 
 
44
 
bracket     ---      Find a bracket containing the minimum.
45
 
 
46
 
 
47
 
 
48
 
"""
49
 
 
50
17
 
51
18
__all__ = ['fmin', 'fmin_powell','fmin_bfgs', 'fmin_ncg', 'fmin_cg',
52
19
           'fminbound','brent', 'golden','bracket','rosen','rosen_der',
53
20
           'rosen_hess', 'rosen_hess_prod', 'brute', 'approx_fprime',
54
21
           'line_search', 'check_grad']
55
22
 
56
 
import Numeric
57
 
import MLab
58
 
from scipy_base import atleast_1d, eye, mgrid, argmin, zeros, shape, \
59
 
     squeeze, isscalar, vectorize, asarray, absolute, sqrt, Inf
60
 
import scipy_base
 
23
import numpy
 
24
from numpy import atleast_1d, eye, mgrid, argmin, zeros, shape, \
 
25
     squeeze, isscalar, vectorize, asarray, absolute, sqrt, Inf, asfarray
61
26
import linesearch
62
 
Num = Numeric
63
 
max = MLab.max
64
 
min = MLab.min
 
27
 
 
28
# These have been copied from Numeric's MLab.py
 
29
# I don't think they made the transition to scipy_core
 
30
def max(m,axis=0):
 
31
    """max(m,axis=0) returns the maximum of m along dimension axis.
 
32
    """
 
33
    m = asarray(m)
 
34
    return numpy.maximum.reduce(m,axis)
 
35
 
 
36
def min(m,axis=0):
 
37
    """min(m,axis=0) returns the minimum of m along dimension axis.
 
38
    """
 
39
    m = asarray(m)
 
40
    return numpy.minimum.reduce(m,axis)
 
41
 
65
42
abs = absolute
66
43
import __builtin__
67
44
pymin = __builtin__.min
68
45
pymax = __builtin__.max
69
46
__version__="0.7"
70
 
_epsilon = sqrt(scipy_base.limits.double_epsilon)
 
47
_epsilon = sqrt(numpy.finfo(float).eps)
71
48
 
72
49
def vecnorm(x, ord=2):
73
50
    if ord == Inf:
74
 
        return scipy_base.amax(abs(x))
 
51
        return numpy.amax(abs(x))
75
52
    elif ord == -Inf:
76
 
        return scipy_base.amin(abs(x))
 
53
        return numpy.amin(abs(x))
77
54
    else:
78
 
        return scipy_base.sum(abs(x)**ord)**(1.0/ord)
79
 
        
 
55
        return numpy.sum(abs(x)**ord,axis=0)**(1.0/ord)
 
56
 
80
57
def rosen(x):  # The Rosenbrock function
81
58
    x = asarray(x)
82
 
    return MLab.sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
 
59
    return numpy.sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0,axis=0)
83
60
 
84
61
def rosen_der(x):
85
62
    x = asarray(x)
86
63
    xm = x[1:-1]
87
64
    xm_m1 = x[:-2]
88
65
    xm_p1 = x[2:]
89
 
    der = MLab.zeros(x.shape,x.typecode())
 
66
    der = numpy.zeros_like(x)
90
67
    der[1:-1] = 200*(xm-xm_m1**2) - 400*(xm_p1 - xm**2)*xm - 2*(1-xm)
91
68
    der[0] = -400*x[0]*(x[1]-x[0]**2) - 2*(1-x[0])
92
69
    der[-1] = 200*(x[-1]-x[-2]**2)
94
71
 
95
72
def rosen_hess(x):
96
73
    x = atleast_1d(x)
97
 
    H = MLab.diag(-400*x[:-1],1) - MLab.diag(400*x[:-1],-1)
98
 
    diagonal = Num.zeros(len(x),x.typecode())
 
74
    H = numpy.diag(-400*x[:-1],1) - numpy.diag(400*x[:-1],-1)
 
75
    diagonal = numpy.zeros(len(x), dtype=x.dtype)
99
76
    diagonal[0] = 1200*x[0]-400*x[1]+2
100
77
    diagonal[-1] = 200
101
78
    diagonal[1:-1] = 202 + 1200*x[1:-1]**2 - 400*x[2:]
102
 
    H = H + MLab.diag(diagonal)
 
79
    H = H + numpy.diag(diagonal)
103
80
    return H
104
81
 
105
82
def rosen_hess_prod(x,p):
106
83
    x = atleast_1d(x)
107
 
    Hp = Num.zeros(len(x),x.typecode())
 
84
    Hp = numpy.zeros(len(x), dtype=x.dtype)
108
85
    Hp[0] = (1200*x[0]**2 - 400*x[1] + 2)*p[0] - 400*x[0]*p[1]
109
86
    Hp[1:-1] = -400*x[:-2]*p[:-2]+(202+1200*x[1:-1]**2-400*x[2:])*p[1:-1] \
110
87
               -400*x[1:-1]*p[2:]
111
88
    Hp[-1] = -400*x[-2]*p[-2] + 200*p[-1]
112
89
    return Hp
113
 
        
114
 
def fmin(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None, maxfun=None, 
115
 
         full_output=0, disp=1, retall=0):
 
90
 
 
91
def wrap_function(function, args):
 
92
    ncalls = [0]
 
93
    def function_wrapper(x):
 
94
        ncalls[0] += 1
 
95
        return function(x, *args)
 
96
    return ncalls, function_wrapper
 
97
 
 
98
def fmin(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None, maxfun=None,
 
99
         full_output=0, disp=1, retall=0, callback=None):
116
100
    """Minimize a function using the downhill simplex algorithm.
117
101
 
118
102
    Description:
119
 
    
 
103
 
120
104
      Uses a Nelder-Mead simplex algorithm to find the minimum of function
121
105
      of one or more variables.
122
106
 
125
109
      func -- the Python function or method to be minimized.
126
110
      x0 -- the initial guess.
127
111
      args -- extra arguments for func.
 
112
      callback -- an optional user-supplied function to call after each
 
113
                  iteration.  It is called as callback(xk), where xk is the
 
114
                  current parameter vector.
128
115
 
129
116
    Outputs: (xopt, {fopt, iter, funcalls, warnflag})
130
117
 
147
134
      full_output -- non-zero if fval and warnflag outputs are desired.
148
135
      disp -- non-zero to print convergence messages.
149
136
      retall -- non-zero to return list of solutions at each iteration
150
 
      
 
137
 
 
138
    See also:
 
139
 
 
140
      fmin, fmin_powell, fmin_cg,
 
141
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
142
      leastsq -- nonlinear least squares minimizer
 
143
 
 
144
      fmin_l_bfgs_b, fmin_tnc,
 
145
             fmin_cobyla -- constrained multivariate optimizers
 
146
 
 
147
      anneal, brute -- global optimizers
 
148
 
 
149
      fminbound, brent, golden, bracket -- local scalar minimizers
 
150
 
 
151
      fsolve -- n-dimenstional root-finding
 
152
 
 
153
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
154
 
 
155
      fixed_point -- scalar fixed-point finder
 
156
 
151
157
      """
152
 
    x0 = asarray(x0)
 
158
    fcalls, func = wrap_function(func, args)
 
159
    x0 = asfarray(x0)
153
160
    N = len(x0)
154
161
    rank = len(x0.shape)
155
162
    if not -1 < rank < 2:
163
170
    one2np1 = range(1,N+1)
164
171
 
165
172
    if rank == 0:
166
 
        sim = Num.zeros((N+1,),x0.typecode())
167
 
    else:        
168
 
        sim = Num.zeros((N+1,N),x0.typecode())
169
 
    fsim = Num.zeros((N+1,),'d')
 
173
        sim = numpy.zeros((N+1,), dtype=x0.dtype)
 
174
    else:
 
175
        sim = numpy.zeros((N+1,N), dtype=x0.dtype)
 
176
    fsim = numpy.zeros((N+1,), float)
170
177
    sim[0] = x0
171
178
    if retall:
172
179
        allvecs = [sim[0]]
173
 
    fsim[0] = apply(func,(x0,)+args)
 
180
    fsim[0] = func(x0)
174
181
    nonzdelt = 0.05
175
182
    zdelt = 0.00025
176
183
    for k in range(0,N):
177
 
        y = Num.array(x0,copy=1)
 
184
        y = numpy.array(x0,copy=True)
178
185
        if y[k] != 0:
179
186
            y[k] = (1+nonzdelt)*y[k]
180
187
        else:
181
188
            y[k] = zdelt
182
189
 
183
190
        sim[k+1] = y
184
 
        f = apply(func,(y,)+args)
 
191
        f = func(y)
185
192
        fsim[k+1] = f
186
193
 
187
 
    ind = Num.argsort(fsim)
188
 
    fsim = Num.take(fsim,ind)  # sort so sim[0,:] has the lowest function value
189
 
    sim = Num.take(sim,ind,0)
190
 
    
 
194
    ind = numpy.argsort(fsim)
 
195
    fsim = numpy.take(fsim,ind,0)
 
196
    # sort so sim[0,:] has the lowest function value
 
197
    sim = numpy.take(sim,ind,0)
 
198
 
191
199
    iterations = 1
192
 
    funcalls = N+1
193
 
    
194
 
    while (funcalls < maxfun and iterations < maxiter):
195
 
        if (max(Num.ravel(abs(sim[1:]-sim[0]))) <= xtol \
 
200
 
 
201
    while (fcalls[0] < maxfun and iterations < maxiter):
 
202
        if (max(numpy.ravel(abs(sim[1:]-sim[0]))) <= xtol \
196
203
            and max(abs(fsim[0]-fsim[1:])) <= ftol):
197
204
            break
198
205
 
199
 
        xbar = Num.add.reduce(sim[:-1],0) / N
 
206
        xbar = numpy.add.reduce(sim[:-1],0) / N
200
207
        xr = (1+rho)*xbar - rho*sim[-1]
201
 
        fxr = apply(func,(xr,)+args)
202
 
        funcalls = funcalls + 1
 
208
        fxr = func(xr)
203
209
        doshrink = 0
204
210
 
205
211
        if fxr < fsim[0]:
206
212
            xe = (1+rho*chi)*xbar - rho*chi*sim[-1]
207
 
            fxe = apply(func,(xe,)+args)
208
 
            funcalls = funcalls + 1
 
213
            fxe = func(xe)
209
214
 
210
215
            if fxe < fxr:
211
216
                sim[-1] = xe
221
226
                # Perform contraction
222
227
                if fxr < fsim[-1]:
223
228
                    xc = (1+psi*rho)*xbar - psi*rho*sim[-1]
224
 
                    fxc = apply(func,(xc,)+args)
225
 
                    funcalls = funcalls + 1
 
229
                    fxc = func(xc)
226
230
 
227
231
                    if fxc <= fxr:
228
232
                        sim[-1] = xc
232
236
                else:
233
237
                    # Perform an inside contraction
234
238
                    xcc = (1-psi)*xbar + psi*sim[-1]
235
 
                    fxcc = apply(func,(xcc,)+args)
236
 
                    funcalls = funcalls + 1
 
239
                    fxcc = func(xcc)
237
240
 
238
241
                    if fxcc < fsim[-1]:
239
242
                        sim[-1] = xcc
244
247
                if doshrink:
245
248
                    for j in one2np1:
246
249
                        sim[j] = sim[0] + sigma*(sim[j] - sim[0])
247
 
                        fsim[j] = apply(func,(sim[j],)+args)
248
 
                    funcalls = funcalls + N
 
250
                        fsim[j] = func(sim[j])
249
251
 
250
 
        ind = Num.argsort(fsim)
251
 
        sim = Num.take(sim,ind,0)
252
 
        fsim = Num.take(fsim,ind)
253
 
        iterations = iterations + 1
 
252
        ind = numpy.argsort(fsim)
 
253
        sim = numpy.take(sim,ind,0)
 
254
        fsim = numpy.take(fsim,ind,0)
 
255
        if callback is not None:
 
256
            callback(sim[0])
 
257
        iterations += 1
254
258
        if retall:
255
 
            allvecs.append(sim[0])        
 
259
            allvecs.append(sim[0])
256
260
 
257
261
    x = sim[0]
258
262
    fval = min(fsim)
259
263
    warnflag = 0
260
264
 
261
 
    if funcalls >= maxfun:
 
265
    if fcalls[0] >= maxfun:
262
266
        warnflag = 1
263
267
        if disp:
264
268
            print "Warning: Maximum number of function evaluations has "\
272
276
            print "Optimization terminated successfully."
273
277
            print "         Current function value: %f" % fval
274
278
            print "         Iterations: %d" % iterations
275
 
            print "         Function evaluations: %d" % funcalls
 
279
            print "         Function evaluations: %d" % fcalls[0]
276
280
 
277
281
 
278
282
    if full_output:
279
 
        retlist = x, fval, iterations, funcalls, warnflag
 
283
        retlist = x, fval, iterations, fcalls[0], warnflag
280
284
        if retall:
281
285
            retlist += (allvecs,)
282
 
    else: 
 
286
    else:
283
287
        retlist = x
284
288
        if retall:
285
289
            retlist = (x, allvecs)
302
306
    dc = c-a
303
307
    if (db == 0) or (dc == 0) or (b==c): return None
304
308
    denom = (db*dc)**2 * (db-dc)
305
 
    [A,B] = Num.dot([[dc**2, -db**2],[-dc**3, db**3]],[fb-fa-C*db,fc-fa-C*dc])
 
309
    [A,B] = numpy.dot([[dc**2, -db**2],[-dc**3, db**3]],[fb-fa-C*db,fc-fa-C*dc])
306
310
    A /= denom
307
311
    B /= denom
308
312
    radical = B*B-3*A*C
311
315
    xmin = a + (-B + sqrt(radical))/(3*A)
312
316
    return xmin
313
317
 
314
 
    
 
318
 
315
319
def _quadmin(a,fa,fpa,b,fb):
316
320
    # finds the minimizer for a quadratic polynomial that goes through
317
321
    #  the points (a,fa), (b,fb) with derivative at a of fpa
336
340
    while 1:
337
341
        # interpolate to find a trial step length between a_lo and a_hi
338
342
        # Need to choose interpolation here.  Use cubic interpolation and then if the
339
 
        #  result is within delta * dalpha or outside of the interval bounded by a_lo or a_hi 
 
343
        #  result is within delta * dalpha or outside of the interval bounded by a_lo or a_hi
340
344
        #  then use quadratic interpolation, if the result is still too close, then use bisection
341
345
 
342
346
        dalpha = a_hi-a_lo;
362
366
#            else: print "Using quadratic."
363
367
#        else: print "Using cubic."
364
368
 
365
 
        # Check new value of a_j 
 
369
        # Check new value of a_j
366
370
 
367
371
        phi_aj = phi(a_j)
368
372
        if (phi_aj > phi0 + c1*a_j*derphi0) or (phi_aj >= phi_lo):
371
375
            a_hi = a_j
372
376
            phi_hi = phi_aj
373
377
        else:
374
 
            derphi_aj = derphi(a_j)            
 
378
            derphi_aj = derphi(a_j)
375
379
            if abs(derphi_aj) <= -c2*derphi0:
376
380
                a_star = a_j
377
381
                val_star = phi_aj
382
386
                a_rec = a_hi
383
387
                a_hi = a_lo
384
388
                phi_hi = phi_lo
385
 
            else:                
 
389
            else:
386
390
                phi_rec = phi_lo
387
391
                a_rec = a_lo
388
392
            a_lo = a_j
393
397
            a_star = a_j
394
398
            val_star = phi_aj
395
399
            valprime_star = None
396
 
            break    
 
400
            break
397
401
    return a_star, val_star, valprime_star
398
402
 
399
403
def line_search(f, myfprime, xk, pk, gfk, old_fval, old_old_fval,
400
404
                args=(), c1=1e-4, c2=0.9, amax=50):
401
 
    """Find alpha that satisfies strong Wolfe conditions. 
402
 
    
403
 
    Uses the line search algorithm to enforce strong Wolfe conditions 
 
405
    """Find alpha that satisfies strong Wolfe conditions.
 
406
 
 
407
    Uses the line search algorithm to enforce strong Wolfe conditions
404
408
    Wright and Nocedal, 'Numerical Optimization', 1999, pg. 59-60
405
409
 
406
 
    For the zoom phase it uses an algorithm by 
 
410
    For the zoom phase it uses an algorithm by
407
411
    Outputs: (alpha0, gc, fc)
408
412
    """
409
413
 
424
428
            fprime = myfprime[0]
425
429
            newargs = (f,eps) + args
426
430
            _ls_ingfk = fprime(xk+alpha*pk,*newargs)  # store for later use
427
 
            return Num.dot(_ls_ingfk,pk)
 
431
            return numpy.dot(_ls_ingfk,pk)
428
432
    else:
429
433
        fprime = myfprime
430
434
        def phiprime(alpha):
431
435
            global _ls_gc, _ls_ingfk
432
436
            _ls_gc += 1
433
437
            _ls_ingfk = fprime(xk+alpha*pk,*args)  # store for later use
434
 
            return Num.dot(_ls_ingfk,pk)
 
438
            return numpy.dot(_ls_ingfk,pk)
435
439
 
436
440
    alpha0 = 0
437
441
    phi0 = old_fval
438
 
    derphi0 = Num.dot(gfk,pk)
 
442
    derphi0 = numpy.dot(gfk,pk)
439
443
 
440
444
    alpha1 = pymin(1.0,1.01*2*(phi0-old_old_fval)/derphi0)
 
445
 
 
446
    if alpha1 == 0:
 
447
        # This shouldn't happen. Perhaps the increment has slipped below
 
448
        # machine precision?  For now, set the return variables skip the
 
449
        # useless while loop, and raise warnflag=2 due to possible imprecision.
 
450
        alpha_star = None
 
451
        fval_star = old_fval
 
452
        old_fval = old_old_fval
 
453
        fprime_star = None
 
454
 
441
455
    phi_a1 = phi(alpha1)
442
456
    #derphi_a1 = phiprime(alpha1)  evaluated below
443
457
 
446
460
 
447
461
    i = 1
448
462
    maxiter = 10
449
 
    while 1:         # bracketing phase 
 
463
    while 1:         # bracketing phase
 
464
        if alpha1 == 0:
 
465
            break
450
466
        if (phi_a1 > phi0 + c1*alpha1*derphi0) or \
451
467
           ((phi_a1 >= phi_a0) and (i > 1)):
452
468
            alpha_star, fval_star, fprime_star = \
478
494
        derphi_a0 = derphi_a1
479
495
 
480
496
        # stopping test if lower function not found
481
 
        if (i > maxiter):          
 
497
        if (i > maxiter):
482
498
            alpha_star = alpha1
483
499
            fval_star = phi_a1
484
500
            fprime_star = None
490
506
        #                                     this is the gradient at the next step
491
507
        #                                     no need to compute it again in the outer loop.
492
508
        fprime_star = _ls_ingfk
493
 
        
 
509
 
494
510
    return alpha_star, _ls_fc, _ls_gc, fval_star, old_fval, fprime_star
495
 
    
 
511
 
496
512
 
497
513
def line_search_BFGS(f, xk, pk, gfk, old_fval, args=(), c1=1e-4, alpha0=1):
498
514
    """Minimize over alpha, the function f(xk+alpha pk)
499
515
 
500
516
    Uses the interpolation algorithm (Armiijo backtracking) as suggested by
501
517
    Wright and Nocedal in 'Numerical Optimization', 1999, pg. 56-57
502
 
    
 
518
 
503
519
    Outputs: (alpha, fc, gc)
504
520
    """
505
521
 
507
523
    phi0 = old_fval                            # compute f(xk) -- done in past loop
508
524
    phi_a0 = apply(f,(xk+alpha0*pk,)+args)     # compute f
509
525
    fc = fc + 1
510
 
    derphi0 = Num.dot(gfk,pk)
 
526
    derphi0 = numpy.dot(gfk,pk)
511
527
 
512
528
    if (phi_a0 <= phi0 + c1*alpha0*derphi0):
513
529
        return alpha0, fc, 0, phi_a0
521
537
    if (phi_a1 <= phi0 + c1*alpha1*derphi0):
522
538
        return alpha1, fc, 0, phi_a1
523
539
 
524
 
    # Otherwise loop with cubic interpolation until we find an alpha which 
 
540
    # Otherwise loop with cubic interpolation until we find an alpha which
525
541
    # satifies the first Wolfe condition (since we are backtracking, we will
526
542
    # assume that the value of alpha is not too small and satisfies the second
527
543
    # condition.
535
551
            alpha1**3 * (phi_a0 - phi0 - derphi0*alpha0)
536
552
        b = b / factor
537
553
 
538
 
        alpha2 = (-b + Num.sqrt(abs(b**2 - 3 * a * derphi0))) / (3.0*a)
 
554
        alpha2 = (-b + numpy.sqrt(abs(b**2 - 3 * a * derphi0))) / (3.0*a)
539
555
        phi_a2 = apply(f,(xk+alpha2*pk,)+args)
540
556
        fc = fc + 1
541
557
 
553
569
 
554
570
def approx_fprime(xk,f,epsilon,*args):
555
571
    f0 = apply(f,(xk,)+args)
556
 
    grad = Num.zeros((len(xk),),'d')
557
 
    ei = Num.zeros((len(xk),),'d')
 
572
    grad = numpy.zeros((len(xk),), float)
 
573
    ei = numpy.zeros((len(xk),), float)
558
574
    for k in range(len(xk)):
559
575
        ei[k] = epsilon
560
576
        grad[k] = (apply(f,(xk+ei,)+args) - f0)/epsilon
572
588
 
573
589
def fmin_bfgs(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf,
574
590
              epsilon=_epsilon, maxiter=None, full_output=0, disp=1,
575
 
              retall=0):
 
591
              retall=0, callback=None):
576
592
    """Minimize a function using the BFGS algorithm.
577
593
 
578
594
    Description:
592
608
      norm -- order of norm (Inf is max, -Inf is min)
593
609
      epsilon -- if fprime is approximated use this value for
594
610
                 the step size (can be scalar or vector)
 
611
      callback -- an optional user-supplied function to call after each
 
612
                  iteration.  It is called as callback(xk), where xk is the
 
613
                  current parameter vector.
595
614
 
596
615
    Outputs: (xopt, {fopt, gopt, Hopt, func_calls, grad_calls, warnflag}, <allvecs>)
597
616
 
614
633
                     and warnflag in addition to xopt.
615
634
      disp -- print convergence message if non-zero.
616
635
      retall -- return a list of results at each iteration if non-zero
 
636
 
 
637
    See also:
 
638
 
 
639
      fmin, fmin_powell, fmin_cg,
 
640
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
641
      leastsq -- nonlinear least squares minimizer
 
642
 
 
643
      fmin_l_bfgs_b, fmin_tnc,
 
644
             fmin_cobyla -- constrained multivariate optimizers
 
645
 
 
646
      anneal, brute -- global optimizers
 
647
 
 
648
      fminbound, brent, golden, bracket -- local scalar minimizers
 
649
 
 
650
      fsolve -- n-dimenstional root-finding
 
651
 
 
652
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
653
 
 
654
      fixed_point -- scalar fixed-point finder
 
655
 
617
656
      """
618
 
    app_fprime = 0
619
 
    if fprime is None:
620
 
        app_fprime = 1
621
 
 
622
657
    x0 = asarray(x0)
623
658
    if maxiter is None:
624
659
        maxiter = len(x0)*200
625
 
    func_calls = 0
626
 
    grad_calls = 0
 
660
    func_calls, f = wrap_function(f, args)
 
661
    if fprime is None:
 
662
        grad_calls, myfprime = wrap_function(approx_fprime, (f, epsilon))
 
663
    else:
 
664
        grad_calls, myfprime = wrap_function(fprime, args)
 
665
    gfk = myfprime(x0)
627
666
    k = 0
628
667
    N = len(x0)
629
 
    I = MLab.eye(N)
 
668
    I = numpy.eye(N,dtype=int)
630
669
    Hk = I
631
 
    old_fval = f(x0,*args)
 
670
    old_fval = f(x0)
632
671
    old_old_fval = old_fval + 5000
633
 
    func_calls += 1
634
 
    if app_fprime:
635
 
        gfk = apply(approx_fprime,(x0,f,epsilon)+args)
636
 
        myfprime = (approx_fprime,epsilon)
637
 
        func_calls = func_calls + len(x0) + 1
638
 
    else:
639
 
        gfk = apply(fprime,(x0,)+args)
640
 
        myfprime = fprime
641
 
        grad_calls = grad_calls + 1
642
672
    xk = x0
643
673
    if retall:
644
674
        allvecs = [x0]
646
676
    warnflag = 0
647
677
    gnorm = vecnorm(gfk,ord=norm)
648
678
    while (gnorm > gtol) and (k < maxiter):
649
 
        pk = -Num.dot(Hk,gfk)
 
679
        pk = -numpy.dot(Hk,gfk)
650
680
        alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
651
681
           linesearch.line_search(f,myfprime,xk,pk,gfk,
652
 
                                  old_fval,old_old_fval,args=args)
 
682
                                  old_fval,old_old_fval)
653
683
        if alpha_k is None:  # line search failed try different one.
654
 
            func_calls = func_calls + fc
655
 
            grad_calls = grad_calls + gc            
656
684
            alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
657
685
                     line_search(f,myfprime,xk,pk,gfk,
658
 
                                 old_fval,old_old_fval,args=args)
659
 
            
660
 
        func_calls = func_calls + fc
661
 
        grad_calls = grad_calls + gc
 
686
                                 old_fval,old_old_fval)
 
687
            if alpha_k is None:
 
688
                # This line search also failed to find a better solution.
 
689
                warnflag = 2
 
690
                break                
662
691
        xkp1 = xk + alpha_k * pk
663
692
        if retall:
664
693
            allvecs.append(xkp1)
665
694
        sk = xkp1 - xk
666
695
        xk = xkp1
667
696
        if gfkp1 is None:
668
 
            if app_fprime:
669
 
                gfkp1 = apply(approx_fprime,(xkp1,f,epsilon)+args)
670
 
                func_calls = func_calls + len(x0) + 1
671
 
            else:
672
 
                gfkp1 = apply(fprime,(xkp1,)+args)
673
 
                grad_calls = grad_calls + 1
 
697
            gfkp1 = myfprime(xkp1)
674
698
 
675
699
        yk = gfkp1 - gfk
676
 
        gfk = gfkp1        
677
 
        k = k + 1
 
700
        gfk = gfkp1
 
701
        if callback is not None:
 
702
            callback(xk)
 
703
        k += 1
678
704
        gnorm = vecnorm(gfk,ord=norm)
679
705
        if (gnorm <= gtol):
680
706
            break
681
707
 
682
708
        try:
683
 
            rhok = 1 / Num.dot(yk,sk)
 
709
            rhok = 1 / (numpy.dot(yk,sk))
684
710
        except ZeroDivisionError:
685
 
            warnflag = 2
686
 
            break
687
 
            #print "Divide by zero encountered:  Hessian calculation reset."
688
 
            #Hk = I
689
 
        else:
690
 
            A1 = I - sk[:,Num.NewAxis] * yk[Num.NewAxis,:] * rhok
691
 
            A2 = I - yk[:,Num.NewAxis] * sk[Num.NewAxis,:] * rhok
692
 
            Hk = Num.dot(A1,Num.dot(Hk,A2)) + rhok * sk[:,Num.NewAxis] \
693
 
                 * sk[Num.NewAxis,:]
 
711
            rhok = 1000.
 
712
            print "Divide-by-zero encountered: rhok assumed large"
 
713
        A1 = I - sk[:,numpy.newaxis] * yk[numpy.newaxis,:] * rhok
 
714
        A2 = I - yk[:,numpy.newaxis] * sk[numpy.newaxis,:] * rhok
 
715
        Hk = numpy.dot(A1,numpy.dot(Hk,A2)) + rhok * sk[:,numpy.newaxis] \
 
716
                 * sk[numpy.newaxis,:]
694
717
 
695
718
    if disp or full_output:
696
719
        fval = old_fval
699
722
            print "Warning: Desired error not necessarily achieved due to precision loss"
700
723
            print "         Current function value: %f" % fval
701
724
            print "         Iterations: %d" % k
702
 
            print "         Function evaluations: %d" % func_calls
703
 
            print "         Gradient evaluations: %d" % grad_calls
704
 
        
 
725
            print "         Function evaluations: %d" % func_calls[0]
 
726
            print "         Gradient evaluations: %d" % grad_calls[0]
 
727
 
705
728
    elif k >= maxiter:
706
729
        warnflag = 1
707
730
        if disp:
708
731
            print "Warning: Maximum number of iterations has been exceeded"
709
732
            print "         Current function value: %f" % fval
710
733
            print "         Iterations: %d" % k
711
 
            print "         Function evaluations: %d" % func_calls
712
 
            print "         Gradient evaluations: %d" % grad_calls
 
734
            print "         Function evaluations: %d" % func_calls[0]
 
735
            print "         Gradient evaluations: %d" % grad_calls[0]
713
736
    else:
714
737
        if disp:
715
738
            print "Optimization terminated successfully."
716
739
            print "         Current function value: %f" % fval
717
740
            print "         Iterations: %d" % k
718
 
            print "         Function evaluations: %d" % func_calls
719
 
            print "         Gradient evaluations: %d" % grad_calls
 
741
            print "         Function evaluations: %d" % func_calls[0]
 
742
            print "         Gradient evaluations: %d" % grad_calls[0]
720
743
 
721
744
    if full_output:
722
 
        retlist = xk, fval, gfk, Hk, func_calls, grad_calls, warnflag
 
745
        retlist = xk, fval, gfk, Hk, func_calls[0], grad_calls[0], warnflag
723
746
        if retall:
724
747
            retlist += (allvecs,)
725
 
    else: 
 
748
    else:
726
749
        retlist = xk
727
750
        if retall:
728
751
            retlist = (xk, allvecs)
731
754
 
732
755
 
733
756
def fmin_cg(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf, epsilon=_epsilon,
734
 
              maxiter=None, full_output=0, disp=1, retall=0):
 
757
              maxiter=None, full_output=0, disp=1, retall=0, callback=None):
735
758
    """Minimize a function with nonlinear conjugate gradient algorithm.
736
759
 
737
760
    Description:
751
774
      norm -- order of vector norm to use
752
775
      epsilon -- if fprime is approximated use this value for
753
776
                 the step size (can be scalar or vector)
 
777
      callback -- an optional user-supplied function to call after each
 
778
                  iteration.  It is called as callback(xk), where xk is the
 
779
                  current parameter vector.
754
780
 
755
781
    Outputs: (xopt, {fopt, func_calls, grad_calls, warnflag}, {allvecs})
756
782
 
771
797
                     and warnflag in addition to xopt.
772
798
      disp -- print convergence message if non-zero.
773
799
      retall -- return a list of results at each iteration if True
 
800
 
 
801
    See also:
 
802
 
 
803
      fmin, fmin_powell, fmin_cg,
 
804
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
805
      leastsq -- nonlinear least squares minimizer
 
806
 
 
807
      fmin_l_bfgs_b, fmin_tnc,
 
808
             fmin_cobyla -- constrained multivariate optimizers
 
809
 
 
810
      anneal, brute -- global optimizers
 
811
 
 
812
      fminbound, brent, golden, bracket -- local scalar minimizers
 
813
 
 
814
      fsolve -- n-dimenstional root-finding
 
815
 
 
816
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
817
 
 
818
      fixed_point -- scalar fixed-point finder
 
819
 
774
820
      """
775
 
    app_fprime = 0
776
 
    if fprime is None:
777
 
        app_fprime = 1
778
 
 
779
821
    x0 = asarray(x0)
780
822
    if maxiter is None:
781
823
        maxiter = len(x0)*200
782
 
    func_calls = 0
783
 
    grad_calls = 0
 
824
    func_calls, f = wrap_function(f, args)
 
825
    if fprime is None:
 
826
        grad_calls, myfprime = wrap_function(approx_fprime, (f, epsilon))
 
827
    else:
 
828
        grad_calls, myfprime = wrap_function(fprime, args)
 
829
    gfk = myfprime(x0)
784
830
    k = 0
785
831
    N = len(x0)
786
832
    xk = x0
787
 
    old_fval = f(xk,*args)
 
833
    old_fval = f(xk)
788
834
    old_old_fval = old_fval + 5000
789
 
    func_calls +=1 
790
835
 
791
 
    if app_fprime:
792
 
        gfk = apply(approx_fprime,(x0,f,epsilon)+args)
793
 
        myfprime = (approx_fprime,epsilon)
794
 
        func_calls = func_calls + len(x0) + 1
795
 
    else:
796
 
        gfk = apply(fprime,(x0,)+args)
797
 
        myfprime = fprime
798
 
        grad_calls = grad_calls + 1
799
836
    if retall:
800
837
        allvecs = [xk]
801
838
    sk = [2*gtol]
803
840
    pk = -gfk
804
841
    gnorm = vecnorm(gfk,ord=norm)
805
842
    while (gnorm > gtol) and (k < maxiter):
806
 
        deltak = Num.dot(gfk,gfk)
 
843
        deltak = numpy.dot(gfk,gfk)
 
844
 
 
845
        # These values are modified by the line search, even if it fails
 
846
        old_fval_backup = old_fval
 
847
        old_old_fval_backup = old_old_fval
 
848
 
807
849
        alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
808
850
           linesearch.line_search(f,myfprime,xk,pk,gfk,old_fval,
809
 
                                  old_old_fval,args=args,c2=0.4)
 
851
                                  old_old_fval,c2=0.4)
810
852
        if alpha_k is None:  # line search failed -- use different one.
811
 
            func_calls += fc
812
 
            grad_calls += gc                  
813
853
            alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
814
854
                     line_search(f,myfprime,xk,pk,gfk,
815
 
                                 old_fval,old_old_fval,args=args)
816
 
        func_calls += fc
817
 
        grad_calls += gc        
 
855
                                 old_fval_backup,old_old_fval_backup)
 
856
            if alpha_k is None or alpha_k == 0:
 
857
                # This line search also failed to find a better solution.
 
858
                warnflag = 2
 
859
                break
818
860
        xk = xk + alpha_k*pk
819
861
        if retall:
820
862
            allvecs.append(xk)
821
863
        if gfkp1 is None:
822
 
            if app_fprime:
823
 
                gfkp1 = apply(approx_fprime,(xk,f,epsilon)+args)
824
 
                func_calls = func_calls + len(x0) + 1
825
 
            else:
826
 
                gfkp1 = apply(fprime,(xk,)+args)
827
 
                grad_calls = grad_calls + 1
828
 
 
 
864
            gfkp1 = myfprime(xk)
829
865
        yk = gfkp1 - gfk
830
 
        beta_k = pymax(0,Num.dot(yk,gfkp1)/deltak)
 
866
        beta_k = pymax(0,numpy.dot(yk,gfkp1)/deltak)
831
867
        pk = -gfkp1 + beta_k * pk
832
868
        gfk = gfkp1
833
869
        gnorm = vecnorm(gfk,ord=norm)
834
 
        k = k + 1
835
 
        
836
 
        
 
870
        if callback is not None:
 
871
            callback(xk)
 
872
        k += 1
 
873
 
 
874
 
837
875
    if disp or full_output:
838
876
        fval = old_fval
839
877
    if warnflag == 2:
841
879
            print "Warning: Desired error not necessarily achieved due to precision loss"
842
880
            print "         Current function value: %f" % fval
843
881
            print "         Iterations: %d" % k
844
 
            print "         Function evaluations: %d" % func_calls
845
 
            print "         Gradient evaluations: %d" % grad_calls
846
 
        
 
882
            print "         Function evaluations: %d" % func_calls[0]
 
883
            print "         Gradient evaluations: %d" % grad_calls[0]
 
884
 
847
885
    elif k >= maxiter:
848
886
        warnflag = 1
849
887
        if disp:
850
888
            print "Warning: Maximum number of iterations has been exceeded"
851
889
            print "         Current function value: %f" % fval
852
890
            print "         Iterations: %d" % k
853
 
            print "         Function evaluations: %d" % func_calls
854
 
            print "         Gradient evaluations: %d" % grad_calls
 
891
            print "         Function evaluations: %d" % func_calls[0]
 
892
            print "         Gradient evaluations: %d" % grad_calls[0]
855
893
    else:
856
894
        if disp:
857
895
            print "Optimization terminated successfully."
858
896
            print "         Current function value: %f" % fval
859
897
            print "         Iterations: %d" % k
860
 
            print "         Function evaluations: %d" % func_calls
861
 
            print "         Gradient evaluations: %d" % grad_calls
 
898
            print "         Function evaluations: %d" % func_calls[0]
 
899
            print "         Gradient evaluations: %d" % grad_calls[0]
862
900
 
863
901
 
864
902
    if full_output:
865
 
        retlist = xk, fval, func_calls, grad_calls, warnflag
 
903
        retlist = xk, fval, func_calls[0], grad_calls[0], warnflag
866
904
        if retall:
867
905
            retlist += (allvecs,)
868
 
    else: 
 
906
    else:
869
907
        retlist = xk
870
908
        if retall:
871
909
            retlist = (xk, allvecs)
873
911
    return retlist
874
912
 
875
913
def fmin_ncg(f, x0, fprime, fhess_p=None, fhess=None, args=(), avextol=1e-5,
876
 
             epsilon=_epsilon, maxiter=None, full_output=0, disp=1, retall=0):
 
914
             epsilon=_epsilon, maxiter=None, full_output=0, disp=1, retall=0,
 
915
             callback=None):
877
916
    """Description:
878
917
 
879
918
    Minimize the function, f, whose gradient is given by fprime using the
895
934
 
896
935
    epsilon -- if fhess is approximated use this value for
897
936
                 the step size (can be scalar or vector)
 
937
    callback -- an optional user-supplied function to call after each
 
938
                iteration.  It is called as callback(xk), where xk is the
 
939
                current parameter vector.
898
940
 
899
941
  Outputs: (xopt, {fopt, fcalls, gcalls, hcalls, warnflag},{allvecs})
900
942
 
901
943
    xopt -- the minimizer of f
902
 
    
 
944
 
903
945
    fopt -- the value of the function at xopt: fopt = f(xopt)
904
946
    fcalls -- the number of function calls.
905
947
    gcalls -- the number of gradient calls.
911
953
  Additional Inputs:
912
954
 
913
955
    avextol -- Convergence is assumed when the average relative error in
914
 
               the minimizer falls below this amount.  
 
956
               the minimizer falls below this amount.
915
957
    maxiter -- Maximum number of iterations to allow.
916
958
    full_output -- If non-zero return the optional outputs.
917
959
    disp -- If non-zero print convergence message.
918
 
    retall -- return a list of results at each iteration if True    
919
 
    
 
960
    retall -- return a list of results at each iteration if True
 
961
 
920
962
  Remarks:
921
963
 
922
964
    Only one of fhess_p or fhess need be given.  If fhess is provided,
924
966
    provided, then the hessian product will be approximated using finite
925
967
    differences on fprime.
926
968
 
 
969
  See also:
 
970
 
 
971
      fmin, fmin_powell, fmin_cg,
 
972
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
973
      leastsq -- nonlinear least squares minimizer
 
974
 
 
975
      fmin_l_bfgs_b, fmin_tnc,
 
976
             fmin_cobyla -- constrained multivariate optimizers
 
977
 
 
978
      anneal, brute -- global optimizers
 
979
 
 
980
      fminbound, brent, golden, bracket -- local scalar minimizers
 
981
 
 
982
      fsolve -- n-dimenstional root-finding
 
983
 
 
984
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
985
 
 
986
      fixed_point -- scalar fixed-point finder
 
987
 
927
988
    """
928
 
 
929
989
    x0 = asarray(x0)
930
 
    fcalls = 0
931
 
    gcalls = 0
 
990
    fcalls, f = wrap_function(f, args)
 
991
    gcalls, fprime = wrap_function(fprime, args)
932
992
    hcalls = 0
933
993
    if maxiter is None:
934
994
        maxiter = len(x0)*200
935
 
    
 
995
 
936
996
    xtol = len(x0)*avextol
937
997
    update = [2*xtol]
938
998
    xk = x0
939
999
    if retall:
940
1000
        allvecs = [xk]
941
1001
    k = 0
942
 
    old_fval = f(x0,*args)
943
 
    fcalls += 1
944
 
    while (Num.add.reduce(abs(update)) > xtol) and (k < maxiter):
 
1002
    old_fval = f(x0)
 
1003
    while (numpy.add.reduce(abs(update)) > xtol) and (k < maxiter):
945
1004
        # Compute a search direction pk by applying the CG method to
946
1005
        #  del2 f(xk) p = - grad f(xk) starting from 0.
947
 
        b = -apply(fprime,(xk,)+args)
948
 
        gcalls = gcalls + 1
949
 
        maggrad = Num.add.reduce(abs(b))
950
 
        eta = min([0.5,Num.sqrt(maggrad)])
 
1006
        b = -fprime(xk)
 
1007
        maggrad = numpy.add.reduce(abs(b))
 
1008
        eta = min([0.5,numpy.sqrt(maggrad)])
951
1009
        termcond = eta * maggrad
952
 
        xsupi = 0
 
1010
        xsupi = zeros(len(x0), dtype=x0.dtype)
953
1011
        ri = -b
954
1012
        psupi = -ri
955
1013
        i = 0
956
 
        dri0 = Num.dot(ri,ri)
 
1014
        dri0 = numpy.dot(ri,ri)
957
1015
 
958
1016
        if fhess is not None:             # you want to compute hessian once.
959
1017
            A = apply(fhess,(xk,)+args)
960
1018
            hcalls = hcalls + 1
961
1019
 
962
 
        while Num.add.reduce(abs(ri)) > termcond:
 
1020
        while numpy.add.reduce(abs(ri)) > termcond:
963
1021
            if fhess is None:
964
1022
                if fhess_p is None:
965
 
                    Ap = apply(approx_fhess_p,(xk,psupi,fprime,epsilon)+args)
966
 
                    gcalls = gcalls + 2
 
1023
                    Ap = approx_fhess_p(xk,psupi,fprime,epsilon)
967
1024
                else:
968
 
                    Ap = apply(fhess_p,(xk,psupi)+args)
 
1025
                    Ap = fhess_p(xk,psupi, *args)
969
1026
                    hcalls = hcalls + 1
970
1027
            else:
971
 
                Ap = Num.dot(A,psupi)
 
1028
                Ap = numpy.dot(A,psupi)
972
1029
            # check curvature
973
 
            curv = Num.dot(psupi,Ap)
974
 
            if (curv <= 0):
 
1030
            Ap = asarray(Ap).squeeze() # get rid of matrices...
 
1031
            curv = numpy.dot(psupi,Ap)
 
1032
            if curv == 0.0:
 
1033
                break
 
1034
            elif curv < 0:
975
1035
                if (i > 0):
976
1036
                    break
977
1037
                else:
980
1040
            alphai = dri0 / curv
981
1041
            xsupi = xsupi + alphai * psupi
982
1042
            ri = ri + alphai * Ap
983
 
            dri1 = Num.dot(ri,ri)
 
1043
            dri1 = numpy.dot(ri,ri)
984
1044
            betai = dri1 / dri0
985
1045
            psupi = -ri + betai * psupi
986
1046
            i = i + 1
987
 
            dri0 = dri1          # update Num.dot(ri,ri) for next time.
988
 
    
 
1047
            dri0 = dri1          # update numpy.dot(ri,ri) for next time.
 
1048
 
989
1049
        pk = xsupi  # search direction is solution to system.
990
1050
        gfk = -b    # gradient at xk
991
 
        alphak, fc, gc, old_fval = line_search_BFGS(f,xk,pk,gfk,old_fval,args)
992
 
        fcalls = fcalls + fc
993
 
        gcalls = gcalls + gc
 
1051
        alphak, fc, gc, old_fval = line_search_BFGS(f,xk,pk,gfk,old_fval)
994
1052
 
995
1053
        update = alphak * pk
996
 
        xk = xk + update
 
1054
        xk = xk + update        # upcast if necessary
 
1055
        if callback is not None:
 
1056
            callback(xk)
997
1057
        if retall:
998
1058
            allvecs.append(xk)
999
 
        k = k + 1
 
1059
        k += 1
1000
1060
 
1001
1061
    if disp or full_output:
1002
1062
        fval = old_fval
1006
1066
            print "Warning: Maximum number of iterations has been exceeded"
1007
1067
            print "         Current function value: %f" % fval
1008
1068
            print "         Iterations: %d" % k
1009
 
            print "         Function evaluations: %d" % fcalls
1010
 
            print "         Gradient evaluations: %d" % gcalls
 
1069
            print "         Function evaluations: %d" % fcalls[0]
 
1070
            print "         Gradient evaluations: %d" % gcalls[0]
1011
1071
            print "         Hessian evaluations: %d" % hcalls
1012
1072
    else:
1013
1073
        warnflag = 0
1015
1075
            print "Optimization terminated successfully."
1016
1076
            print "         Current function value: %f" % fval
1017
1077
            print "         Iterations: %d" % k
1018
 
            print "         Function evaluations: %d" % fcalls
1019
 
            print "         Gradient evaluations: %d" % gcalls
 
1078
            print "         Function evaluations: %d" % fcalls[0]
 
1079
            print "         Gradient evaluations: %d" % gcalls[0]
1020
1080
            print "         Hessian evaluations: %d" % hcalls
1021
 
            
 
1081
 
1022
1082
    if full_output:
1023
 
        retlist = xk, fval, fcalls, gcalls, hcalls, warnflag
 
1083
        retlist = xk, fval, fcalls[0], gcalls[0], hcalls, warnflag
1024
1084
        if retall:
1025
1085
            retlist += (allvecs,)
1026
 
    else: 
 
1086
    else:
1027
1087
        retlist = xk
1028
1088
        if retall:
1029
1089
            retlist = (xk, allvecs)
1030
1090
 
1031
1091
    return retlist
1032
 
    
1033
 
 
1034
 
def fminbound(func, x1, x2, args=(), xtol=1e-5, maxfun=500, 
 
1092
 
 
1093
 
 
1094
def fminbound(func, x1, x2, args=(), xtol=1e-5, maxfun=500,
1035
1095
              full_output=0, disp=1):
1036
1096
    """Bounded minimization for scalar functions.
1037
1097
 
1048
1108
      args -- extra arguments to pass to function.
1049
1109
      xtol -- the convergence tolerance.
1050
1110
      maxfun -- maximum function evaluations.
1051
 
      full_output -- Non-zero to return optional outputs. 
 
1111
      full_output -- Non-zero to return optional outputs.
1052
1112
      disp -- Non-zero to print messages.
1053
1113
              0 : no message printing.
1054
1114
              1 : non-convergence notification messages only.
1055
1115
              2 : print a message on convergence too.
1056
 
              3 : print iteration results. 
 
1116
              3 : print iteration results.
1057
1117
 
1058
1118
 
1059
1119
    Outputs: (xopt, {fval, ierr, numfunc})
1063
1123
      ierr -- An error flag (0 if converged, 1 if maximum number of
1064
1124
              function calls reached).
1065
1125
      numfunc -- The number of function calls.
 
1126
 
 
1127
  See also:
 
1128
 
 
1129
      fmin, fmin_powell, fmin_cg,
 
1130
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
1131
      leastsq -- nonlinear least squares minimizer
 
1132
 
 
1133
      fmin_l_bfgs_b, fmin_tnc,
 
1134
             fmin_cobyla -- constrained multivariate optimizers
 
1135
 
 
1136
      anneal, brute -- global optimizers
 
1137
 
 
1138
      fminbound, brent, golden, bracket -- local scalar minimizers
 
1139
 
 
1140
      fsolve -- n-dimenstional root-finding
 
1141
 
 
1142
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
1143
 
 
1144
      fixed_point -- scalar fixed-point finder
 
1145
 
1066
1146
    """
1067
1147
 
1068
1148
    if x1 > x2:
1092
1172
        print (" ")
1093
1173
        print (header)
1094
1174
        print "%5.0f   %12.6g %12.6g %s" % (fmin_data + (step,))
1095
 
    
 
1175
 
1096
1176
 
1097
1177
    while ( abs(xf-xm) > (tol2 - 0.5*(b-a)) ):
1098
1178
        golden = 1
1115
1195
                step = '       parabolic'
1116
1196
 
1117
1197
                if ((x-a) < tol2) or ((b-x) < tol2):
1118
 
                    si = Numeric.sign(xm-xf) + ((xm-xf)==0)
 
1198
                    si = numpy.sign(xm-xf) + ((xm-xf)==0)
1119
1199
                    rat = tol1*si
1120
1200
            else:      # do a golden section step
1121
1201
                golden = 1
1128
1208
            rat = golden_mean*e
1129
1209
            step = '       golden'
1130
1210
 
1131
 
        si = Numeric.sign(rat) + (rat == 0)
 
1211
        si = numpy.sign(rat) + (rat == 0)
1132
1212
        x = xf + si*max([abs(rat), tol1])
1133
1213
        fu = func(x,*args)
1134
1214
        num += 1
1135
1215
        fmin_data = (num, x, fu)
1136
1216
        if disp > 2:
1137
1217
            print "%5.0f   %12.6g %12.6g %s" % (fmin_data + (step,))
1138
 
                
 
1218
 
1139
1219
        if fu <= fx:
1140
1220
            if x >= xf:
1141
1221
                a = xf
1163
1243
            flag = 1
1164
1244
            fval = fx
1165
1245
            if disp > 0:
1166
 
                _endprint(x, flag, fval, maxfun, tol, disp)
 
1246
                _endprint(x, flag, fval, maxfun, xtol, disp)
1167
1247
            if full_output:
1168
1248
                return xf, fval, flag, num
1169
1249
            else:
1172
1252
    fval = fx
1173
1253
    if disp > 0:
1174
1254
        _endprint(x, flag, fval, maxfun, xtol, disp)
1175
 
    
 
1255
 
1176
1256
    if full_output:
1177
1257
        return xf, fval, flag, num
1178
1258
    else:
1189
1269
    Uses inverse parabolic interpolation when possible to speed up convergence
1190
1270
    of golden section method.
1191
1271
 
 
1272
 
 
1273
    See also:
 
1274
 
 
1275
      fmin, fmin_powell, fmin_cg,
 
1276
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
1277
      leastsq -- nonlinear least squares minimizer
 
1278
 
 
1279
      fmin_l_bfgs_b, fmin_tnc,
 
1280
             fmin_cobyla -- constrained multivariate optimizers
 
1281
 
 
1282
      anneal, brute -- global optimizers
 
1283
 
 
1284
      fminbound, brent, golden, bracket -- local scalar minimizers
 
1285
 
 
1286
      fsolve -- n-dimenstional root-finding
 
1287
 
 
1288
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
1289
 
 
1290
      fixed_point -- scalar fixed-point finder
 
1291
 
1192
1292
    """
1193
1293
    _mintol = 1.0e-11
1194
1294
    _cg = 0.3819660
1207
1307
        assert ((fb<fa) and (fb < fc)), "Not a bracketing interval."
1208
1308
        funcalls = 3
1209
1309
    else:
1210
 
        raise ValuError, "Bracketing interval must be length 2 or 3 sequence."
 
1310
        raise ValueError, "Bracketing interval must be length 2 or 3 sequence."
1211
1311
 
1212
1312
    x=w=v=xb
1213
1313
    fw=fv=fx=apply(func, (x,)+args)
1225
1325
        if abs(x-xmid) < (tol2-0.5*(b-a)):  # check for convergence
1226
1326
            xmin=x; fval=fx
1227
1327
            break
1228
 
        if (abs(deltax) <= tol1):           
 
1328
        if (abs(deltax) <= tol1):
1229
1329
            if (x>=xmid): deltax=a-x       # do a golden section step
1230
1330
            else: deltax=b-x
1231
1331
            rat = _cg*deltax
1265
1365
                v=w; w=u; fv=fw; fw=fu
1266
1366
            elif (fu<=fv) or (v==x) or (v==w):
1267
1367
                v=u; fv=fu
1268
 
        else: 
 
1368
        else:
1269
1369
            if (u >= x): a = x
1270
1370
            else: b = x
1271
1371
            v=w; w=x; x=u
1272
1372
            fv=fw; fw=fx; fx=fu
1273
 
        
 
1373
 
1274
1374
    xmin = x
1275
1375
    fval = fx
1276
1376
    if full_output:
1277
1377
        return xmin, fval, iter, funcalls
1278
1378
    else:
1279
1379
        return xmin
1280
 
    
 
1380
 
1281
1381
def golden(func, args=(), brack=None, tol=_epsilon, full_output=0):
1282
1382
    """ Given a function of one-variable and a possible bracketing interval,
1283
1383
    return the minimum of the function isolated to a fractional precision of
1287
1387
    (see bracket)
1288
1388
 
1289
1389
    Uses analog of bisection method to decrease the bracketed interval.
 
1390
 
 
1391
    See also:
 
1392
 
 
1393
      fmin, fmin_powell, fmin_cg,
 
1394
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
1395
      leastsq -- nonlinear least squares minimizer
 
1396
 
 
1397
      fmin_l_bfgs_b, fmin_tnc,
 
1398
             fmin_cobyla -- constrained multivariate optimizers
 
1399
 
 
1400
      anneal, brute -- global optimizers
 
1401
 
 
1402
      fminbound, brent, golden, bracket -- local scalar minimizers
 
1403
 
 
1404
      fsolve -- n-dimenstional root-finding
 
1405
 
 
1406
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
1407
 
 
1408
      fixed_point -- scalar fixed-point finder
 
1409
 
1290
1410
    """
1291
1411
    if brack is None:
1292
1412
        xa,xb,xc,fa,fb,fc,funcalls = bracket(func, args=args)
1303
1423
        assert ((fb<fa) and (fb < fc)), "Not a bracketing interval."
1304
1424
        funcalls = 3
1305
1425
    else:
1306
 
        raise ValuError, "Bracketing interval must be length 2 or 3 sequence."
 
1426
        raise ValueError, "Bracketing interval must be length 2 or 3 sequence."
1307
1427
 
1308
1428
    _gR = 0.61803399
1309
1429
    _gC = 1.0-_gR
1335
1455
    if full_output:
1336
1456
        return xmin, fval, funcalls
1337
1457
    else:
1338
 
        return xmin    
1339
 
 
1340
 
 
1341
 
def bracket(func, xa=0.0, xb=1.0, args=(), grow_limit=110.0):
 
1458
        return xmin
 
1459
 
 
1460
 
 
1461
def bracket(func, xa=0.0, xb=1.0, args=(), grow_limit=110.0, maxiter=1000):
1342
1462
    """Given a function and distinct initial points, search in the downhill
1343
1463
    direction (as defined by the initital points) and return new points
1344
1464
    xa, xb, xc that bracket the minimum of the function:
1348
1468
    _verysmall_num = 1e-21
1349
1469
    fa = apply(func, (xa,)+args)
1350
1470
    fb = apply(func, (xb,)+args)
1351
 
    if (fa < fb):                      # Switch so fa > fb 
 
1471
    if (fa < fb):                      # Switch so fa > fb
1352
1472
        dum = xa; xa = xb; xb = dum
1353
1473
        dum = fa; fa = fb; fb = dum
1354
1474
    xc = xb + _gold*(xb-xa)
1365
1485
            denom = 2.0*val
1366
1486
        w = xb - ((xb-xc)*tmp2-(xb-xa)*tmp1)/denom
1367
1487
        wlim = xb + grow_limit*(xc-xb)
1368
 
        if iter > 1000:
1369
 
            raise RunTimeError, "Too many iterations."
 
1488
        if iter > maxiter:
 
1489
            raise RuntimeError, "Too many iterations."
 
1490
        iter += 1
1370
1491
        if (w-xc)*(xb-w) > 0.0:
1371
1492
            fw = apply(func, (w,)+args)
1372
1493
            funcalls += 1
1397
1518
        xa=xb; xb=xc; xc=w
1398
1519
        fa=fb; fb=fc; fc=fw
1399
1520
    return xa, xb, xc, fa, fb, fc, funcalls
1400
 
            
1401
 
            
1402
 
global _powell_funcalls
1403
 
 
1404
 
def _myfunc(alpha, func, x0, direc, args=()):
1405
 
    funcargs = (x0 + alpha * direc,)+args
1406
 
    return func(*funcargs)
1407
 
    
1408
 
def _linesearch_powell(func, p, xi, args=(), tol=1e-3):
 
1521
 
 
1522
 
 
1523
 
 
1524
def _linesearch_powell(func, p, xi, tol=1e-3):
1409
1525
    # line-search algorithm using fminbound
1410
1526
    #  find the minimium of the function
1411
1527
    #  func(x0+ alpha*direc)
1412
 
    global _powell_funcalls
1413
 
    extra_args = (func, p, xi) + args
1414
 
    alpha_min, fret, iter, num = brent(_myfunc, args=extra_args,
1415
 
                                           full_output=1, tol=tol)
 
1528
    def myfunc(alpha):
 
1529
        return func(p + alpha * xi)
 
1530
    alpha_min, fret, iter, num = brent(myfunc, full_output=1, tol=tol)
1416
1531
    xi = alpha_min*xi
1417
 
    _powell_funcalls += num
1418
1532
    return squeeze(fret), p+xi, xi
1419
 
    
 
1533
 
1420
1534
 
1421
1535
def fmin_powell(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None,
1422
 
                maxfun=None, full_output=0, disp=1, retall=0):
 
1536
                maxfun=None, full_output=0, disp=1, retall=0, callback=None):
1423
1537
    """Minimize a function using modified Powell's method.
1424
1538
 
1425
1539
    Description:
1426
 
    
 
1540
 
1427
1541
      Uses a modification of Powell's method to find the minimum of a function
1428
1542
      of N variables
1429
1543
 
1432
1546
      func -- the Python function or method to be minimized.
1433
1547
      x0 -- the initial guess.
1434
1548
      args -- extra arguments for func.
 
1549
      callback -- an optional user-supplied function to call after each
 
1550
                  iteration.  It is called as callback(xk), where xk is the
 
1551
                  current parameter vector.
1435
1552
 
1436
1553
    Outputs: (xopt, {fopt, xi, direc, iter, funcalls, warnflag}, {allvecs})
1437
1554
 
1456
1573
      disp -- non-zero to print convergence messages.
1457
1574
      retall -- non-zero to return a list of the solution at each iteration
1458
1575
 
 
1576
    See also:
 
1577
 
 
1578
      fmin, fmin_powell, fmin_cg,
 
1579
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
1580
      leastsq -- nonlinear least squares minimizer
 
1581
 
 
1582
      fmin_l_bfgs_b, fmin_tnc,
 
1583
             fmin_cobyla -- constrained multivariate optimizers
 
1584
 
 
1585
      anneal, brute -- global optimizers
 
1586
 
 
1587
      fminbound, brent, golden, bracket -- local scalar minimizers
 
1588
 
 
1589
      fsolve -- n-dimenstional root-finding
 
1590
 
 
1591
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
1592
 
 
1593
      fixed_point -- scalar fixed-point finder
 
1594
 
1459
1595
      """
1460
 
    global _powell_funcalls
 
1596
    # we need to use a mutable object here that we can update in the
 
1597
    # wrapper function
 
1598
    fcalls, func = wrap_function(func, args)
1461
1599
    x = asarray(x0)
1462
1600
    if retall:
1463
1601
        allvecs = [x]
1470
1608
    if maxfun is None:
1471
1609
        maxfun = N * 1000
1472
1610
 
1473
 
    direc = eye(N,typecode='d')
1474
 
    fval = squeeze(apply(func, (x,)+args))
1475
 
    _powell_funcalls = 1
 
1611
    direc = eye(N,dtype=float)
 
1612
    fval = squeeze(func(x))
1476
1613
    x1 = x.copy()
1477
1614
    iter = 0;
1478
1615
    ilist = range(N)
1479
 
    while 1:
 
1616
    while True:
1480
1617
        fx = fval
1481
1618
        bigind = 0
1482
1619
        delta = 0.0
1483
1620
        for i in ilist:
1484
1621
            direc1 = direc[i]
1485
1622
            fx2 = fval
1486
 
            fval, x, direc1 = _linesearch_powell(func, x, direc1, args=args, tol=xtol*100)
 
1623
            fval, x, direc1 = _linesearch_powell(func, x, direc1, tol=xtol*100)
1487
1624
            if (fx2 - fval) > delta:
1488
1625
                delta = fx2 - fval
1489
1626
                bigind = i
1490
1627
        iter += 1
 
1628
        if callback is not None:
 
1629
            callback(x)
1491
1630
        if retall:
1492
1631
            allvecs.append(x)
1493
1632
        if (2.0*(fx - fval) <= ftol*(abs(fx)+abs(fval))+1e-20): break
1494
 
        if _powell_funcalls >= maxfun: break
 
1633
        if fcalls[0] >= maxfun: break
1495
1634
        if iter >= maxiter: break
1496
1635
 
1497
1636
        # Construct the extrapolated point
1498
1637
        direc1 = x - x1
1499
1638
        x2 = 2*x - x1
1500
1639
        x1 = x.copy()
1501
 
        fx2 = squeeze(apply(func, (x2,)+args))
1502
 
        _powell_funcalls +=1
 
1640
        fx2 = squeeze(func(x2))
1503
1641
 
1504
1642
        if (fx > fx2):
1505
1643
            t = 2.0*(fx+fx2-2.0*fval)
1508
1646
            temp = fx-fx2
1509
1647
            t -= delta*temp*temp
1510
1648
            if t < 0.0:
1511
 
                fval, x, direc1 = _linesearch_powell(func, x, direc1, args=args, tol=xtol*100)
 
1649
                fval, x, direc1 = _linesearch_powell(func, x, direc1, tol=xtol*100)
1512
1650
                direc[bigind] = direc[-1]
1513
 
                direc[-1] = direc1            
 
1651
                direc[-1] = direc1
1514
1652
 
1515
1653
    warnflag = 0
1516
 
    if _powell_funcalls >= maxfun:
 
1654
    if fcalls[0] >= maxfun:
1517
1655
        warnflag = 1
1518
1656
        if disp:
1519
1657
            print "Warning: Maximum number of function evaluations has "\
1527
1665
            print "Optimization terminated successfully."
1528
1666
            print "         Current function value: %f" % fval
1529
1667
            print "         Iterations: %d" % iter
1530
 
            print "         Function evaluations: %d" % _powell_funcalls
 
1668
            print "         Function evaluations: %d" % fcalls[0]
1531
1669
 
1532
1670
    x = squeeze(x)
1533
1671
 
1534
1672
    if full_output:
1535
 
        retlist = x, fval, direc, iter, _powell_funcalls, warnflag
 
1673
        retlist = x, fval, direc, iter, fcalls[0], warnflag
1536
1674
        if retall:
1537
1675
            retlist += (allvecs,)
1538
 
    else: 
 
1676
    else:
1539
1677
        retlist = x
1540
1678
        if retall:
1541
1679
            retlist = (x, allvecs)
1542
1680
 
1543
1681
    return retlist
1544
 
    
1545
 
    
 
1682
 
 
1683
 
1546
1684
 
1547
1685
 
1548
1686
def _endprint(x, flag, fval, maxfun, xtol, disp):
1565
1703
 
1566
1704
    func        -- Function to be optimized
1567
1705
    ranges       -- Tuple where each element is a tuple of parameters
1568
 
                      or a slice object to be handed to scipy.mgrid
 
1706
                      or a slice object to be handed to numpy.mgrid
1569
1707
 
1570
1708
    args        -- Extra arguments to function.
1571
1709
    Ns          -- Default number of samples if not given
1578
1716
    grid        -- tuple with same length as x0 representing the
1579
1717
                    evaluation grid
1580
1718
    Jout        -- Function values over grid:  Jout = func(*grid)
 
1719
 
 
1720
    See also:
 
1721
 
 
1722
      fmin, fmin_powell, fmin_cg,
 
1723
             fmin_bfgs, fmin_ncg -- multivariate local optimizers
 
1724
      leastsq -- nonlinear least squares minimizer
 
1725
 
 
1726
      fmin_l_bfgs_b, fmin_tnc,
 
1727
             fmin_cobyla -- constrained multivariate optimizers
 
1728
 
 
1729
      anneal, brute -- global optimizers
 
1730
 
 
1731
      fminbound, brent, golden, bracket -- local scalar minimizers
 
1732
 
 
1733
      fsolve -- n-dimenstional root-finding
 
1734
 
 
1735
      brentq, brenth, ridder, bisect, newton -- one-dimensional root-finding
 
1736
 
 
1737
      fixed_point -- scalar fixed-point finder
 
1738
 
1581
1739
    """
1582
1740
    N = len(ranges)
1583
1741
    if N > 40:
1590
1748
            lrange[k] = slice(*lrange[k])
1591
1749
    if (N==1):
1592
1750
        lrange = lrange[0]
1593
 
        
 
1751
 
1594
1752
    def _scalarfunc(*params):
1595
1753
        params = squeeze(asarray(params))
1596
1754
        return func(params,*args)
1597
 
        
 
1755
 
1598
1756
    vecfunc = vectorize(_scalarfunc)
1599
1757
    grid = mgrid[lrange]
1600
1758
    if (N==1):
1601
1759
        grid = (grid,)
1602
1760
    Jout = vecfunc(*grid)
1603
1761
    Nshape = shape(Jout)
1604
 
    indx = argmin(Jout.flat)
1605
 
    Nindx = zeros(N)
1606
 
    xmin = zeros(N,'d')
 
1762
    indx = argmin(Jout.ravel(),axis=-1)
 
1763
    Nindx = zeros(N,int)
 
1764
    xmin = zeros(N,float)
1607
1765
    for k in range(N-1,-1,-1):
1608
1766
        thisN = Nshape[k]
1609
1767
        Nindx[k] = indx % Nshape[k]
1620
1778
        xmin = vals[0]
1621
1779
        Jmin = vals[1]
1622
1780
        if vals[-1] > 0:
1623
 
            print "Warning: Final optimization did not succeed"        
 
1781
            print "Warning: Final optimization did not succeed"
1624
1782
    if full_output:
1625
1783
        return xmin, Jmin, grid, Jout
1626
1784
    else:
1627
1785
        return xmin
1628
1786
 
1629
 
            
1630
 
if __name__ == "__main__":
1631
 
    import string
 
1787
 
 
1788
def main():
1632
1789
    import time
1633
1790
 
1634
 
    
1635
1791
    times = []
1636
1792
    algor = []
1637
1793
    x0 = [0.8,1.2,0.7]
1688
1844
    print x
1689
1845
    times.append(time.time() - start)
1690
1846
    algor.append('Newton-CG with hessian product')
1691
 
    
 
1847
 
1692
1848
 
1693
1849
    print
1694
1850
    print "Newton-CG with full Hessian"
1705
1861
    print "===========\t\t\t      ========="
1706
1862
    for k in range(len(algor)):
1707
1863
        print algor[k], "\t -- ", times[k]
1708
 
        
1709
 
 
1710
 
 
1711
 
 
1712
 
 
1713
 
 
1714
 
 
1715
 
 
1716
 
 
1717
 
 
1718
 
 
1719
 
 
1720
 
 
1721
 
 
1722
 
 
 
1864
 
 
1865
if __name__ == "__main__":
 
1866
    main()