1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23   
 24  """Cauchy Point trust region nonlinear 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, sqrt 
 31   
 32   
 33  from minfx.base_classes import Min, Trust_region 
 34   
 35   
 36 -def cauchy_point(func=None, dfunc=None, d2func=None, args=(), x0=None, func_tol=1e-25, grad_tol=None, maxiter=1e6, delta_max=1e5, delta0=1.0, eta=0.2, full_output=0, print_flag=0, print_prefix=""): 
  37      """Cauchy Point trust region algorithm. 
 38   
 39      Page 69 from 'Numerical Optimization' by Jorge Nocedal and Stephen J. Wright, 1999, 2nd ed.  The Cauchy point is defined by:: 
 40   
 41                           delta 
 42          pCk  =  - tau_k ------- dfk 
 43                          ||dfk|| 
 44   
 45      where: 
 46   
 47          - delta_k is the trust region radius, 
 48          - dfk is the gradient vector, 
 49   
 50      and:: 
 51   
 52                   / 1                        if dfk . Bk . dfk <= 0 
 53          tau_k = < 
 54                   \ min(||dfk||**2/(delta . dfk . Bk . dfk), 1)    otherwise. 
 55      """ 
 56   
 57      if print_flag: 
 58          if print_flag >= 2: 
 59              print(print_prefix) 
 60          print(print_prefix) 
 61          print(print_prefix + "Cauchy point minimisation") 
 62          print(print_prefix + "~~~~~~~~~~~~~~~~~~~~~~~~~") 
 63      min = Cauchy_point(func, dfunc, d2func, args, x0, func_tol, grad_tol, maxiter, delta_max, delta0, eta, full_output, print_flag, print_prefix) 
 64      results = min.minimise() 
 65      return results 
  66   
 67   
 69 -    def __init__(self, func, dfunc, d2func, args, x0, func_tol, grad_tol, maxiter, delta_max, delta0, eta, full_output, print_flag, print_prefix): 
  70          """Class for Cauchy Point trust region minimisation specific functions. 
 71   
 72          Unless you know what you are doing, you should call the function 'cauchy_point' rather than using this class. 
 73          """ 
 74   
 75           
 76          self.func = func 
 77          self.dfunc = dfunc 
 78          self.d2func = d2func 
 79          self.args = args 
 80          self.xk = x0 
 81          self.func_tol = func_tol 
 82          self.grad_tol = grad_tol 
 83          self.maxiter = maxiter 
 84          self.full_output = full_output 
 85          self.print_flag = print_flag 
 86          self.print_prefix = print_prefix 
 87          self.delta_max = delta_max 
 88          self.delta = delta0 
 89          self.eta = eta 
 90   
 91           
 92          self.f_count = 0 
 93          self.g_count = 0 
 94          self.h_count = 0 
 95   
 96           
 97          self.warning = None 
 98   
 99           
100          self.setup_conv_tests() 
101   
102           
103          self.fk, self.f_count = self.func(*(self.xk,)+self.args), self.f_count + 1 
104          self.dfk, self.g_count = self.dfunc(*(self.xk,)+self.args), self.g_count + 1 
105          self.d2fk, self.h_count = self.d2func(*(self.xk,)+self.args), self.h_count + 1 
 106   
107   
109          """Find the Cauchy point.""" 
110   
111           
112          curv = dot(self.dfk, dot(self.d2fk, self.dfk)) 
113          norm_dfk = sqrt(dot(self.dfk, self.dfk)) 
114   
115           
116          if curv <= 0.0: 
117              self.tau_k = 1.0 
118          else: 
119              self.tau_k = min(norm_dfk ** 3 / (self.delta * curv), 1.0) 
120   
121          if self.print_flag >= 2: 
122              print(self.print_prefix + "dfk . Bk . dfk: " + repr(curv)) 
123              print(self.print_prefix + "tau_k:          " + repr(self.tau_k)) 
124   
125           
126          self.pk = - self.tau_k * self.delta * self.dfk / norm_dfk 
127   
128           
129          self.xk_new = self.xk + self.pk 
130          self.fk_new, self.f_count = self.func(*(self.xk_new,)+self.args), self.f_count + 1 
131          self.dfk_new, self.g_count = self.dfunc(*(self.xk_new,)+self.args), self.g_count + 1 
 132   
133   
135          """Update function. 
136   
137          Function to update the function value, gradient vector, and Hessian matrix. 
138          """ 
139   
140          self.xk = self.xk_new * 1.0 
141          self.fk = self.fk_new 
142          self.dfk = self.dfk_new * 1.0 
143          self.d2fk, self.h_count = self.d2func(*(self.xk,)+self.args), self.h_count + 1