diff --git a/nifty/minimization/line_searching/line_search_strong_wolfe.py b/nifty/minimization/line_searching/line_search_strong_wolfe.py index bcf9d1052953a37c8559ba8577b945dcad51ca38..a03ef67c88407be82c9e8ce1e7fc447d896d465a 100644 --- a/nifty/minimization/line_searching/line_search_strong_wolfe.py +++ b/nifty/minimization/line_searching/line_search_strong_wolfe.py @@ -26,16 +26,17 @@ class LineSearchStrongWolfe(LineSearch): Algorithm contains two stages. It begins whit a trial step length and it keeps increasing the it until it finds an acceptable step length or an - interval. In the second stage the Zoom algorithm is performed which - decreases the size of the interval until an acceptable step length is found. + interval. If it does not satisfy the Wolfe conditions it performs the Zoom + algorithm (second stage). By interpolating it decreases the size of the + interval until an acceptable step length is found. Parameters ---------- - c1 : scalar + c1 : float Parameter for Armijo condition rule. (Default: 1e-4) - c2 : scalar + c2 : float Parameter for curvature condition rule. (Default: 0.9) - max_step_size : scalar + max_step_size : float Maximum step allowed in to be made in the descent direction. (Default: 50) max_iterations : integer @@ -51,13 +52,12 @@ class LineSearchStrongWolfe(LineSearch): Parameter for Armijo condition rule. c2 : float Parameter for curvature condition rule. - max_step_size : scalar + max_step_size : float Maximum step allowed in to be made in the descent direction. max_iterations : integer Maximum number of iterations performed by the line search algorithm. max_zoom_iterations : integer Maximum number of iterations performed by the zoom algorithm. - """ @@ -77,8 +77,9 @@ class LineSearchStrongWolfe(LineSearch): def perform_line_search(self, energy, pk, f_k_minus_1=None): """Performs the first stage of the algorithm. - Its starts with a trial step size and it keeps increasing it until it - satisfy the strong Wolf conditions. + It starts with a trial step size and it keeps increasing it until it + satisfy the strong Wolf conditions. It also performs the descent and + returns the optimal step length and the new enrgy. Parameters ---------- @@ -88,9 +89,18 @@ class LineSearchStrongWolfe(LineSearch): pk : Field Unit vector pointing into the search direction. f_k_minus_1 : float - Value of the function (energy) which will be minimized at the k-1 + Value of the fuction (which is being minimized) at the k-1 iteration of the line search procedure. (Default: None) - + + Returns + ------- + alpha_star : float + The optimal step length in the descent direction. + phi_star : float + Value of the energy after the performed descent. + energy_star : Energy object + The new Energy object on the new position. + """ self._set_line_energy(energy, pk, f_k_minus_1=f_k_minus_1) @@ -183,7 +193,47 @@ class LineSearchStrongWolfe(LineSearch): def _zoom(self, alpha_lo, alpha_hi, phi_0, phiprime_0, phi_lo, phiprime_lo, phi_hi, c1, c2): - + """Performs the second stage of the line search algorithm. + + If the first stage was not successful then the Zoom algorithm tries to + find a suitable step length by using bisection, quadratic, cubic + interpolation. + + Parameters + ---------- + alpha_lo : float + The lower boundary for the step length interval. + alph_hi : float + The upper boundary for the step length interval. + phi_0 : float + Value of the energy at the starting point of the line search + algorithm. + phiprime_0 : Field + Gradient at the starting point of the line search algorithm. + phi_lo : float + Value of the energy if we perform a step of length alpha_lo in + descent direction. + phiprime_lo : Field + Gradient at the nwe position if we perform a step of length + alpha_lo in descent direction. + phi_hi : float + Value of the energy if we perform a step of length alpha_hi in + descent direction. + c1 : float + Parameter for Armijo condition rule. + c2 : float + Parameter for curvature condition rule. + + Returns + ------- + alpha_star : float + The optimal step length in the descent direction. + phi_star : float + Value of the energy after the performed descent. + energy_star : Energy object + The new Energy object on the new position. + + """ max_iterations = self.max_zoom_iterations # define the cubic and quadratic interpolant checks cubic_delta = 0.2 # cubic @@ -254,12 +304,36 @@ class LineSearchStrongWolfe(LineSearch): return alpha_star, phi_star, energy_star def _cubicmin(self, a, fa, fpa, b, fb, c, fc): - """ + """Estimating the minimum with cubic interpolation. + Finds the minimizer for a cubic polynomial that goes through the - points (a,fa), (b,fb), and (c,fc) with derivative at a of fpa. + points ( a,f(a) ), ( b,f(b) ), and ( c,f(c) ) with derivative at point a of fpa. + f(x) = A *(x-a)^3 + B*(x-a)^2 + C*(x-a) + D If no minimizer can be found return None + + Parameters + ---------- + a : float + Selected point. + fa : float + Value of polynomial at point a. + fpa : Field + Derivative at point a. + b : float + Selected point. + fb : float + Value of polynomial at point b. + c : float + Selected point. + fc : float + Value of polynomial at point c. + + Returns + ------- + xmin : float + Position of the approximated minimum. + """ - # f(x) = A *(x-a)^3 + B*(x-a)^2 + C*(x-a) + D with np.errstate(divide='raise', over='raise', invalid='raise'): try: @@ -285,9 +359,29 @@ class LineSearchStrongWolfe(LineSearch): return xmin def _quadmin(self, a, fa, fpa, b, fb): - """ + """Estimating the minimum with quadratic interpolation. + Finds the minimizer for a quadratic polynomial that goes through - the points (a,fa), (b,fb) with derivative at a of fpa, + the points ( a,f(a) ), ( b,f(b) ) with derivative at point a of fpa. + f(x) = B*(x-a)^2 + C*(x-a) + D + + Parameters + ---------- + a : float + Selected point. + fa : float + Value of polynomial at point a. + fpa : Field + Derivative at point a. + b : float + Selected point. + fb : float + Value of polynomial at point b. + + Returns + ------- + xmin : float + Position of the approximated minimum. """ # f(x) = B*(x-a)^2 + C*(x-a) + D with np.errstate(divide='raise', over='raise', invalid='raise'): diff --git a/nifty/minimization/quasi_newton_minimizer.py b/nifty/minimization/quasi_newton_minimizer.py index afb1f703a5e731d8779ad36cdc6dca080aea598e..448ebddc837450b81178d00e99fe09d35de0de3d 100644 --- a/nifty/minimization/quasi_newton_minimizer.py +++ b/nifty/minimization/quasi_newton_minimizer.py @@ -40,7 +40,7 @@ class QuasiNewtonMinimizer(Loggable, object): callback : function, *optional* Function f(energy, iteration_number) specified by the user to print iteration number and energy value at every iteration step. It accepts - a function(energy) and integer(iteration_number). (default: None) + an Energy object(energy) and integer(iteration_number). (default: None) convergence_tolerance : scalar Tolerance specifying convergence. (default: 1E-4) convergence_level : integer @@ -63,7 +63,7 @@ class QuasiNewtonMinimizer(Loggable, object): callback : function Function f(energy, iteration_number) specified by the user to print iteration number and energy value at every iteration step. It accepts - a function(energy) and integer(iteration_number). + an Energy object(energy) and integer(iteration_number). Raises ------ @@ -102,7 +102,7 @@ class QuasiNewtonMinimizer(Loggable, object): Returns ------- - x : Field + energy : Energy object Latest `energy` of the minimization. convergence : integer Latest convergence level indicating whether the minimization