Source code for pymor.algorithms.line_search

# This file is part of the pyMOR project (http://www.pymor.org).
# Copyright 2013-2020 pyMOR developers and contributors. All rights reserved.
# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

from pymor.core.defaults import defaults
from pymor.core.logger import getLogger


[docs]@defaults('alpha_init', 'tau', 'beta', 'maxiter') def armijo(f, starting_point, direction, grad=None, initial_value=None, alpha_init=1.0, tau=0.5, beta=0.0001, maxiter=10): """Armijo line search algorithm. This method computes a step size such that the Armijo condition (see [NW06]_, p. 33) is fulfilled. Parameters ---------- f Real-valued function that can be evaluated for its value. starting_point A |VectorArray| of length 1 containing the starting point of the line search. direction Descent direction along which the line search is performed. grad Gradient of `f` in the point `starting_point`. initial_value Value of `f` in the point `starting_point`. alpha_init Initial step size that is gradually reduced. tau The fraction by which the step size is reduced in each iteration. beta Control parameter to adjust the required decrease of the function value of `f`. maxiter Use `alpha_init` as default if the iteration count reaches this value without finding a point fulfilling the Armijo condition. Returns ------- alpha Step size computed according to the Armijo condition. """ assert alpha_init > 0 assert 0 < tau < 1 assert maxiter > 0 # Start line search with step size of alpha_init alpha = alpha_init # Compute initial function value if initial_value is None: initial_value = f(starting_point) iteration = 0 slope = 0.0 # Compute slope if gradient is provided if grad: slope = min(grad.dot(direction), 0.0) while True: # Compute new function value current_value = f(starting_point + alpha * direction) # Check the Armijo condition if current_value < initial_value + alpha * beta * slope: break # Check if maxiter is reached if iteration >= maxiter: # Use default value as step size alpha = alpha_init # Log warning logger = getLogger('pymor.algorithms.line_search.armijo') logger.warning(f'Reached maximum number of line search steps; using initial step size of {alpha_init} instead') break iteration += 1 # Adjust step size alpha *= tau return alpha