def __call__(self, s): ''' s: direction vector ''' xk = self.xk Bk = self.get_hessian_approx() fk = self.f(*tvec(xk)) gk = self.g(*tvec(xk)) return fk + s.T * gk + self.sigma * norm(s)**3 / 3.
def _backtracking_routine(f, g, x, d, s, a, b): fx = f(*tvec(x)) gtd = (g(*tvec(x)).T * d)[0, 0] t = s while 1: td = t * d fxtd = f(*tvec(x + td)) if fx - fxtd >= -a * t * gtd: return t t = b * t
def report(self): if self.converged(): print 'Iterative method successful:', 'Terminated after %d iterations' % self.num_iter print 'Optimal Point %s of value = %.5f' % ( self.xk, self.objective(*tvec(self.xk))) print 'Gradient error: %.5f' % self.gradient(*tvec(self.xk)) elif self.num_iter >= self.max_iter: print 'Reached a maximum of %d iterations' % self.max_iter print 'Method may not be convergent' print 'Gradient error: %.5f' % self.gradient(*tvec(self.xk)) else: print 'The optimizer has not yet finished.' print 'Current iterate', self.xk print 'Current value', self.objective(*tvec(self.xk))
def __init__(self, x0, f, g, H=None, B0=None, tol=1e-7, max_iter=10**8): ''' x0: starting vector f: smooth objective function g: gradint of f H: Hessian of f B0: Approximation to H(x0) ''' self.xk = x0 self.n = len(x0) self.num_iter = 0 self.objective = f self.gradient = g self.hessian = H self.Bk = B0 self.direction = None self.step_length = 0 self.tol = tol # tolerence self.max_iter = max_iter # set default functions ## search direction: by default, pick a random vector with components in (0,1). Naive self.search_dir_fn = lambda f, g, xk: np.random.random(self.n) ## Step length: always 1 by default self.step_length_fn = lambda f, g, xk, dk: 1 ## stopping crietrion: stop when g(xk) has length less then the tolerance self.stopping_fn = lambda g, xk: norm(g(*tvec(xk))) < self.tol ## Hessian approximation update: unchanged by default self.hessian_approx_update = lambda Bk, xk, dk, tk: Bk
def __init__(self, f, x0, g, H=None, B0=None, sigma0=1, Q=None, T=None): ''' Q is a rectangular matrix such that Q^T*Q = I, n-dimensional T = Q^T*B*Q, which will be computed if not specified, where B is whichever matrix we use for Hessian approximation (could be H(xk) itself) ''' ARCModel.__init__(self, f, x0, g, H, B0, sigma0) # if Q is None: # Q = np.eye(self.n) #T = ARCModel.get_hessian_approx(self) self.T = T self.Q = Q #self._actual_g = self.g self.g = (lambda g: (lambda x: self.Q.T * g(*tvec(x))))(self.g)
def __init__(self, f, x0, g, H=None, B0=None, sigma0=1): ''' f: objective function to minimize x0: starting vector g: gradient of f H: exact hessian of f (set to None if unknown) B0: initial approximation to the hessian of f at iterate x0 sigma0>0: initial regularization parameter ''' self.f = f self.xk = x0 self.g = g self.H = H self.n = len(x0) if B0 is None: if H is None: raise ValueError( 'Unknown Hessian: initial guess must be specified') B0 = H(*tvec(x0)) self.Bk = B0 self.sigma = sigma0 self.sigma_update_fn = lambda x: x self.hessian_update_function = lambda B, x, d: B if H is None else H( *tvec(x))
def get_hessian_approx(self): return self.Bk if self.Bk is not None else H(*tvec(self.xk))
def __init__(self, x0, f, g, H=None, B0=None, tol=1e-7, max_iter=10**8): DescentMethod.__init__(self, x0, f, g, H, B0, tol, max_iter) self.search_dir_fn = lambda f, g, xk: -g(*tvec(xk))
def find_opt_length(f, g, x, d): if self.ray_fn is None: ray_fn = lambda x, d, t: f(*tvec(x + td)) else: ray_fn = self.ray_fn return self.min_routine(lambda t: ray_fn(x, d, t))