1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Hestenes-Stiefel conjugate gradient optimization.
25
26 This file is part of the U{minfx optimisation library<https://sourceforge.net/projects/minfx>}.
27 """
28
29
30 from numpy import dot
31
32
33 from minfx.base_classes import Conjugate_gradient, Line_search, Min
34
35
36 -def hestenes_stiefel(func=None, dfunc=None, args=(), x0=None, min_options=None, func_tol=1e-25, grad_tol=None, maxiter=1e6, a0=1.0, mu=0.0001, eta=0.1, full_output=0, print_flag=0, print_prefix=""):
37 """Hestenes-Stiefel conjugate gradient algorithm.
38
39 Page 122 from 'Numerical Optimization' by Jorge Nocedal and Stephen J. Wright, 1999, 2nd ed. The algorithm is:
40
41 - Given x0
42 - Evaluate f0 = f(x0), g0 = g(x0)
43 - Set p0 = -g0, k = 0
44 - while g0 != 0:
45 - Compute ak and set xk+1 = xk + ak.pk
46 - Evaluate gk+1
47 - bk+1 = dot(gk+1, (gk+1 - gk)) / dot((gk+1 - gk), pk)
48 - pk+1 = -gk+1 + bk+1.pk
49 - k = k + 1
50 """
51
52 if print_flag:
53 if print_flag >= 2:
54 print(print_prefix)
55 print(print_prefix)
56 print(print_prefix + "Hestenes-Stiefel conjugate gradient minimisation")
57 print(print_prefix + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
58 min = Hestenes_stiefel(func, dfunc, args, x0, min_options, func_tol, grad_tol, maxiter, a0, mu, eta, full_output, print_flag, print_prefix)
59 if min.init_failure:
60 print(print_prefix + "Initialisation of minimisation has failed.")
61 return None
62 results = min.minimise()
63 return results
64
65
67 - def __init__(self, func, dfunc, args, x0, min_options, func_tol, grad_tol, maxiter, a0, mu, eta, full_output, print_flag, print_prefix):
68 """Class for Hestenes-Stiefel conjugate gradient minimisation specific functions.
69
70 Unless you know what you are doing, you should call the function 'hestenes_stiefel' rather than using this class.
71 """
72
73
74 self.func = func
75 self.dfunc = dfunc
76 self.args = args
77 self.xk = x0
78 self.func_tol = func_tol
79 self.grad_tol = grad_tol
80 self.maxiter = maxiter
81 self.full_output = full_output
82 self.print_flag = print_flag
83 self.print_prefix = print_prefix
84
85
86 self.a0 = a0
87
88
89 self.mu = mu
90 self.eta = eta
91
92
93 self.init_failure = 0
94
95
96 self.line_search_options(min_options)
97 self.setup_line_search()
98
99
100 self.f_count = 0
101 self.g_count = 0
102 self.h_count = 0
103
104
105 self.warning = None
106
107
108 self.setup_conv_tests()
109
110
111 self.fk, self.f_count = self.func(*(self.xk,)+self.args), self.f_count + 1
112 self.dfk, self.g_count = self.dfunc(*(self.xk,)+self.args), self.g_count + 1
113 self.pk = -self.dfk
114 self.dot_dfk = dot(self.dfk, self.dfk)
115
116
118 """Function to calculate the Hestenes-Stiefel beta value."""
119
120
121 diff = self.dfk_new - self.dfk
122 return dot(self.dfk_new, diff) / dot(diff, self.pk)
123