1
2
3
4
5 """
6 Computes a quasi-Newton step for a specific function at a specific point
7 """
8
9 import numpy
10 import numpy.linalg
11
13 """
14 The Davidson-Fletcher-Powell Quasi-Newton step
15 """
17 """
18 Construct a DFP module
19 - hessian_approx is an approximation of the hessian around the starting point
20 """
21 self.B0 = numpy.linalg.inv(hessian_approx)
22
23 - def __call__(self, function, point, state):
24 """
25 Computes a gradient step based on a function and a point
26 """
27 if 'Bk' not in state:
28 Bk = self.B0.copy()
29 gradient = function.gradient(point)
30 else:
31 Bk = state['Bk']
32 oldParams = state['old_parameters']
33 newParams = state['new_parameters']
34 gradient = function.gradient(point)
35 oldGradient = state['gradient']
36
37 yk = gradient - oldGradient
38 sk = newParams - oldParams
39 rho = 1/numpy.dot(yk.T, sk)
40 Bk = numpy.dot(numpy.eye(len(gradient), len(gradient)) - rho * numpy.dot(yk[:, numpy.newaxis], sk[numpy.newaxis,:]), numpy.dot(Bk, numpy.eye(len(gradient), len(gradient)) - rho * numpy.dot(sk[:, numpy.newaxis], yk[numpy.newaxis,:]))) + rho * numpy.dot(yk[:, numpy.newaxis], yk[numpy.newaxis,:])
41
42 step = -numpy.dot(Bk, gradient)
43
44 state['Bk'] = Bk
45 state['gradient'] = gradient
46 state['direction'] = step
47 return step
48