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
26 self.a0 = a0
27
28
29 self.mu = mu
30 self.eta = eta
31
32
33 self.f_count = 0
34 self.g_count = 0
35 self.h_count = 0
36
37
38 self.warning = None
39
40
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
46 self.I = identity(len(self.xk), Float64)
47
48
49 self.minimise = self.generic_minimise
50
51
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
62 "Calculate the BFGS direction."
63
64 self.pk = -matrixmultiply(self.d2fk, self.dfk)
65
66
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
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