def fminBFGS(f, x0, fprime=None, args=(), avegtol=1e-5, maxiter=None, fulloutput=0, printmessg=1): """xopt = fminBFGS(f, x0, fprime=None, args=(), avegtol=1e-5, maxiter=None, fulloutput=0, printmessg=1) Optimize the function, f, whose gradient is given by fprime using the quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno (BFGS) See Wright, and Nocedal 'Numerical Optimization', 1999, pg. 198. """ app_fprime = 0 if fprime is None: app_fprime = 1 x0 = Num.asarray(x0) if maxiter is None: maxiter = len(x0)*200 func_calls = 0 grad_calls = 0 k = 0 N = len(x0) gtol = N*avegtol I = MLab.eye(N) Hk = I if app_fprime: gfk = apply(approx_fprime,(x0,f)+args) func_calls = func_calls + len(x0) + 1 else: gfk = apply(fprime,(x0,)+args) grad_calls = grad_calls + 1 xk = x0 sk = [2*gtol] while (Num.add.reduce(abs(gfk)) > gtol) and (k < maxiter): pk = -Num.dot(Hk,gfk) alpha_k, fc, gc = line_search_BFGS(f,xk,pk,gfk,args) func_calls = func_calls + fc xkp1 = xk + alpha_k * pk sk = xkp1 - xk xk = xkp1 if app_fprime: gfkp1 = apply(approx_fprime,(xkp1,f)+args) func_calls = func_calls + gc + len(x0) + 1 else: gfkp1 = apply(fprime,(xkp1,)+args) grad_calls = grad_calls + gc + 1 yk = gfkp1 - gfk k = k + 1 rhok = 1 / Num.dot(yk,sk) A1 = I - sk[:,Num.NewAxis] * yk[Num.NewAxis,:] * rhok A2 = I - yk[:,Num.NewAxis] * sk[Num.NewAxis,:] * rhok Hk = Num.dot(A1,Num.dot(Hk,A2)) + rhok * sk[:,Num.NewAxis] * sk[Num.NewAxis,:] gfk = gfkp1 if printmessg or fulloutput: fval = apply(f,(xk,)+args) if k >= maxiter: warnflag = 1 if printmessg: print "Warning: Maximum number of iterations has been exceeded" print " Current function value: %f" % fval print " Iterations: %d" % k print " Function evaluations: %d" % func_calls print " Gradient evaluations: %d" % grad_calls else: warnflag = 0 if printmessg: print "Optimization terminated successfully." print " Current function value: %f" % fval print " Iterations: %d" % k print " Function evaluations: %d" % func_calls print " Gradient evaluations: %d" % grad_calls if fulloutput: return xk, fval, func_calls, grad_calls, warnflag else: return xk
def fminBFGS(f, x0, fprime=None, args=(), avegtol=1e-5, maxiter=None, fulloutput=0, printmessg=1): """xopt = fminBFGS(f, x0, fprime=None, args=(), avegtol=1e-5, maxiter=None, fulloutput=0, printmessg=1) Optimize the function, f, whose gradient is given by fprime using the quasi-Newton method of Broyden, Fletcher, Goldfarb, and Shanno (BFGS) See Wright, and Nocedal 'Numerical Optimization', 1999, pg. 198. """ app_fprime = 0 if fprime is None: app_fprime = 1 x0 = Num.asarray(x0) if maxiter is None: maxiter = len(x0) * 200 func_calls = 0 grad_calls = 0 k = 0 N = len(x0) gtol = N * avegtol I = MLab.eye(N) Hk = I if app_fprime: gfk = apply(approx_fprime, (x0, f) + args) func_calls = func_calls + len(x0) + 1 else: gfk = apply(fprime, (x0, ) + args) grad_calls = grad_calls + 1 xk = x0 sk = [2 * gtol] while (Num.add.reduce(abs(gfk)) > gtol) and (k < maxiter): pk = -Num.dot(Hk, gfk) alpha_k, fc, gc = line_search_BFGS(f, xk, pk, gfk, args) func_calls = func_calls + fc xkp1 = xk + alpha_k * pk sk = xkp1 - xk xk = xkp1 if app_fprime: gfkp1 = apply(approx_fprime, (xkp1, f) + args) func_calls = func_calls + gc + len(x0) + 1 else: gfkp1 = apply(fprime, (xkp1, ) + args) grad_calls = grad_calls + gc + 1 yk = gfkp1 - gfk k = k + 1 rhok = 1 / Num.dot(yk, sk) A1 = I - sk[:, Num.NewAxis] * yk[Num.NewAxis, :] * rhok A2 = I - yk[:, Num.NewAxis] * sk[Num.NewAxis, :] * rhok Hk = Num.dot(A1, Num.dot( Hk, A2)) + rhok * sk[:, Num.NewAxis] * sk[Num.NewAxis, :] gfk = gfkp1 if printmessg or fulloutput: fval = apply(f, (xk, ) + args) if k >= maxiter: warnflag = 1 if printmessg: print "Warning: Maximum number of iterations has been exceeded" print " Current function value: %f" % fval print " Iterations: %d" % k print " Function evaluations: %d" % func_calls print " Gradient evaluations: %d" % grad_calls else: warnflag = 0 if printmessg: print "Optimization terminated successfully." print " Current function value: %f" % fval print " Iterations: %d" % k print " Function evaluations: %d" % func_calls print " Gradient evaluations: %d" % grad_calls if fulloutput: return xk, fval, func_calls, grad_calls, warnflag else: return xk