MATLAB Program to Find A Function Minimum

Using the ModifiedNewton's Method

by Namir Shammas

The following program uses the modified Newton's method to find the minimum of a function . The modification part performs a linear search on the calculated guess refinement. This search further improves the refined values for the optimum.

The function modnewton_opt has the following input parameters:

  1. N - number of variables
  2. X - array of initial guesses
  3. gradToler - tolerance for the norm of the slopes
  4. XToler - array of tolerance values for the variables' refinement
  5. MaxIter - maximum number of iterations
  6. myFx - name of the optimized function

The function generates the following output:

  1. X - array of optimized variables
  2. F - function value at optimum
  3. Iters - number of iterations

Here is a sample session to find the optimum for the following function:

y = 10 + (X(1) - 2)^2 + (X(2) + 5)^2

The above function resides in file fx1.m. The search for the optimum 2 variables has the initial guess of [0 0]and a step tolerance vector of [1e-5 1e-5]. The search employs a maximum of 100 iterations and a gradient tolerance of 1e-7.

>> [X,F,Iters] = modnewton_opt(2, [0 0], 1e-7, [1e-5 1e-5], 100, 'fx1')

X =

    2.0000 -5.0000

F =

    10

Iters =

    2

Here is the MATLAB listing:

function y=fx1(X, N)
  y = 10 + (X(1) - 2)^2 + (X(2) + 5)^2;
end

function [X,F,Iters] = modnewton_opt(N, X, gradToler, XToler, MaxIter, myFx)
% Function MODNEWTON_OPT performs multivariate optimization using the
% modified Newton's method.
%
% Input
%
% N - number of variables
% X - array of initial guesses
% gradToler - tolerance for the norm of the slopes
% XToler - array of tolerance values for the variables' refinement
% MaxIter - maximum number of iterations
% myFx - name of the optimized function
%
% Output
%
% X - array of optimized variables
% F - function value at optimum
% Iters - number of iterations
%

bGoOn = true;
Iters = 0;

while bGoOn

  Iters = Iters + 1;
  if Iters > MaxIter
    break;
  end

  g = FirstDerivatives(X, N, myFx);
  fnorm = norm(g);
  if fnorm < gradToler
    break;
  end
  J = SecondDerivatives(X, N, myFx);
  DeltaX = g / J;

  lambda = 0;
  lambda = linsearch(X, N, lambda, DeltaX, myFx);
  X = X + lambda * DeltaX;

  bStop = true;
  for i=1:N
    if abs(lambda * DeltaX(i)) > XToler(i)
      bStop = false;
    end
  end

  bGoOn = ~bStop;

end

F = feval(myFx, X, N);

% end

function y = myFxEx(N, X, DeltaX, lambda, myFx)

  X = X + lambda * DeltaX;
  y = feval(myFx, X, N);

% end

function FirstDerivX = FirstDerivatives(X, N, myFx)

for iVar=1:N
  xt = X(iVar);
  h = 0.01 * (1 + abs(xt));
  X(iVar) = xt + h;
  fp = feval(myFx, X, N);
  X(iVar) = xt - h;
  fm = feval(myFx, X, N);
  X(iVar) = xt;
  FirstDerivX(iVar) = (fp - fm) / 2 / h;
end

% end

function SecondDerivX = SecondDerivatives(X, N, myFx)

for i=1:N
  for j=1:N
    % calculate second derivative?
    if i == j
      f0 = feval(myFx, X, N);
      xt = X(i);
      hx = 0.01 * (1 + abs(xt));
      X(i) = xt + hx;
      fp = feval(myFx, X, N);
      X(i) = xt - hx;
      fm = feval(myFx, X, N);
      X(i) = xt;
      y = (fp - 2 * f0 + fm) / hx ^ 2;
    else
      xt = X(i);
      yt = X(j);
      hx = 0.01 * (1 + abs(xt));
      hy = 0.01 * (1 + abs(yt));
      % calculate fpp;
      X(i) = xt + hx;
      X(j) = yt + hy;
      fpp = feval(myFx, X, N);
      % calculate fmm;
      X(i) = xt - hx;
      X(j) = yt - hy;
      fmm = feval(myFx, X, N);
      % calculate fpm;
      X(i) = xt + hx;
      X(j) = yt - hy;
      fpm = feval(myFx, X, N);
      % calculate fmp
      X(i) = xt - hx;
      X(j) = yt + hy;
      fmp = feval(myFx, X, N);
      X(i) = xt;
      X(j) = yt;
      y = (fpp - fmp - fpm + fmm) / (4 * hx * hy);
    end
    SecondDerivX(i,j) = y;
  end
end

%end

function lambda = linsearch(X, N, lambda, D, myFx)

  MaxIt = 100;
  Toler = 0.000001;

  iter = 0;
  bGoOn = true;
  while bGoOn
    iter = iter + 1;
    if iter > MaxIt
      lambda = 0;
      break
    end

    h = 0.01 * (1 + abs(lambda));
    f0 = myFxEx(N, X, D, lambda, myFx);
    fp = myFxEx(N, X, D, lambda+h, myFx);
    fm = myFxEx(N, X, D, lambda-h, myFx);
    deriv1 = (fp - fm) / 2 / h;
    deriv2 = (fp - 2 * f0 + fm) / h ^ 2;
    diff = deriv1 / deriv2;
    lambda = lambda - diff;
    if abs(diff) < Toler
      bGoOn = false;
    end
  end

% end

BACK

Copyright (c) Namir Shammas. All rights reserved.