Package minimise :: Module bfgs
[hide private]
[frames] | no frames]

Source Code for Module minimise.bfgs

 1  from Numeric import Float64, copy, dot, identity, matrixmultiply, outerproduct 
 2   
 3  from generic_line_search import generic_line_search 
 4  from generic_minimise import generic_minimise 
 5   
 6   
7 -class bfgs(generic_line_search, generic_minimise):
8 - def __init__(self, func, dfunc=None, args=(), x0=None, line_search_algor=None, func_tol=1e-5, maxiter=1000, full_output=0, print_flag=0, a0=1.0, mu=0.0001, eta=0.9):
9 "Class for Quasi-Newton BFGS minimisation specific functions." 10 11 self.func = func 12 self.dfunc = dfunc 13 self.args = args 14 self.xk = x0 15 self.func_tol = func_tol 16 self.maxiter = maxiter 17 self.full_output = full_output 18 self.print_flag = print_flag 19 20 if not line_search_algor: 21 raise NameError, "No line search algorithm has been supplied." 22 else: 23 self.line_search_algor = line_search_algor 24 25 # Set a0. 26 self.a0 = a0 27 28 # Line search constants for the Wolfe conditions. 29 self.mu = mu 30 self.eta = eta 31 32 # Initialise the function, gradient, and hessian evaluation counters. 33 self.f_count = 0 34 self.g_count = 0 35 self.h_count = 0 36 37 # Initialise the warning string. 38 self.warning = None 39 40 # The initial BFGS function value, gradient vector, and BFGS approximation to the inverse hessian matrix. 41 self.fk, self.f_count = apply(self.func, (self.xk,)+self.args), self.f_count + 1 42 self.dfk, self.g_count = apply(self.dfunc, (self.xk,)+self.args), self.g_count + 1 43 self.d2fk = identity(len(self.xk), Float64) 44 45 # Set the Identity matrix I. 46 self.I = identity(len(self.xk), Float64) 47 48 # Minimisation. 49 self.minimise = self.generic_minimise
50 51
52 - def backup_current_data(self):
53 "Function to backup the current data into fk_last, xk_last, dfk_last, and d2fk_last." 54 55 self.fk_last = self.fk 56 self.xk_last = copy.deepcopy(self.xk) 57 self.dfk_last = copy.deepcopy(self.dfk) 58 self.d2fk_last = copy.deepcopy(self.d2fk)
59 60
61 - def dir(self):
62 "Calculate the BFGS direction." 63 64 self.pk = -matrixmultiply(self.d2fk, self.dfk)
65 66
67 - def update_data(self):
68 "Function to update the function value, gradient vector, and the BFGS matrix" 69 70 self.xk = copy.deepcopy(self.xk_new) 71 self.fk, self.f_count = apply(self.func, (self.xk,)+self.args), self.f_count + 1 72 self.dfk, self.g_count = apply(self.dfunc, (self.xk,)+self.args), self.g_count + 1 73 74 # BFGS matrix update. 75 sk = self.xk - self.xk_last 76 yk = self.dfk - self.dfk_last 77 if dot(yk, sk) == 0: 78 raise NameError, "The BFGS matrix is indefinite. This should not occur." 79 80 rk = 1.0 / dot(yk, sk) 81 82 a = self.I - rk*outerproduct(sk, yk) 83 b = self.I - rk*outerproduct(yk, sk) 84 c = rk*outerproduct(sk, sk) 85 matrix = matrixmultiply(matrixmultiply(a, self.d2fk), b) + c 86 self.d2fk = matrix
87