MATLAB Program to Find A Function Minimum

Using the Hooke-Jeeves Directional Search Method

by Namir Shammas

The following program calculates the minimum point of a multi-variable function using the Hooke-Jeeves directional search method.

The function hookejeeves has the following input parameters:

  1. N - number of variables
  2. X - array of initial guesses
  3. StepSize - array of search step sizes
  4. MinStepSize - array of minimum step sizes
  5. fxToler - tolerance for function
  6. MaxIter - maximum number of iterations
  7. myFx - name of the optimized function

The function generates the following output:

  1. X - array of optimized variables
  2. BestF - 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], initial step vector of [0.1 0.1] with a minimum step vector of [1e-5 1e-5]. The search employs a maximum of 1000 iterations and a function tolerance of 1e-7:

>> [X,BestF,Iters] = hookejeeves(2, [0 0], [.1 .1], [1e-5 1e-5], 1e-7, 1000, 'fx1')

X =

    2.0000 -5.0000

BestF =

    10

Iters =

    15

Here is the MATLAB listing:

function [X,BestF,Iters] = hookejeeves(N, X, StepSize, MinStepSize, Eps_Fx, MaxIter, myFx)
% Function HOOKEJEEVS performs multivariate optimization using the
% Hooke-Jeeves search method.
%
% Input
%
% N - number of variables
% X - array of initial guesses 
% StepSize - array of search step sizes
% MinStepSize - array of minimum step sizes
% Eps_Fx - tolerance for difference in successive function values
% MaxIter - maximum number of iterations
% myFx - name of the optimized function
%
% Output
%
% X - array of optimized variables
% BestF - function value at optimum
% Iters - number of iterations
%

Xnew = X;
BestF = feval(myFx, Xnew, N);
LastBestF = 100 * BestF + 100;

bGoOn = true;
Iters = 0;

while bGoOn

  Iters = Iters + 1;
  if Iters > MaxIter
    break;
  end
  
  X = Xnew;
  
  for i=1:N
    bMoved(i) = 0;
    bGoOn2 = true;
    while bGoOn2
      xx = Xnew(i);
      Xnew(i) = xx + StepSize(i);
      F = feval(myFx, Xnew, N);
      if F < BestF
        BestF = F;
        bMoved(i) = 1;
      else
        Xnew(i) = xx - StepSize(i);
        F = feval(myFx, Xnew, N);
        if F < BestF
          BestF = F;
          bMoved(i) = 1;
        else
          Xnew(i) = xx;
          bGoOn2 = false;
        end  
      end  
    end
  end
  
  bMadeAnyMove = sum(bMoved);
  
  if bMadeAnyMove > 0 
    DeltaX = Xnew - X;
    lambda = 0.5;
    lambda = linsearch(X, N, lambda, DeltaX, myFx);
    Xnew = X + lambda * DeltaX;
  end
  
  BestF = feval(myFx, Xnew, N);
  
  % reduce the step size for the dimensions that had no moves
  for i=1:N
    if bMoved(i) == 0
      StepSize(i) = StepSize(i) / 2;
    end
  end
  
  if abs(BestF - LastBestF) < Eps_Fx
    break
  end
  
  LastBest = BestF;
  bStop = true;
  for i=1:N
    if StepSize(i) >= MinStepSize(i)
      bStop = false;
    end  
  end
  
  bGoOn = ~bStop;
  
end

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

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

% 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

%{

Sub DirectSearch()
  Const MAX_VARS = 3
  
  Dim N As Integer, I As Integer
  Dim Row As Integer, MaxIter As Integer
  Dim X(MAX_VARS) As Double, Xnew(MAX_VARS) As Double
  Dim StepSize(MAX_VARS) As Double
  Dim MinStepSize(MAX_VARS) As Double
  Dim Deltax(MAX_VARS) As Double
  Dim F As Double, XX As Double, Lambda As Double
  Dim BestF As Double, LastBestF As Double, EPSF As Double
  Dim bStop As Boolean, bMadeAnyMove As Boolean
  Dim bMoved(MAX_VARS) As Boolean
  
  N = MAX_VARS
  For I = 1 To N
    Xnew(I) = Cells(I + 1, 2)
    StepSize(I) = Cells(I + 1, 3)
    MinStepSize(I) = Cells(I + 1, 4)
  Next I
  EPSF = Cells(2, 1)
  
  Range("E1:Z32000").Clear
  Range("E1").Value = "F(X())"
  Range("E1:Z1").Font.Bold = True
  For I = 1 To N
    Cells(1, 5 + I) = "X(" & I & ")"
    Cells(1, 5 + I + N) = "Step(" & I & ")"
  Next I
  ' calculate and display function value at initial point
  BestF = MyFx(Xnew, N)
  LastBestF = 100 * BestF + 100
  
  Row = 1
  Do
    Row = Row + 1
    
    For I = 1 To N
      X(I) = Xnew(I)
    Next I
    
    For I = 1 To N
      bMoved(I) = False
      Do
        XX = Xnew(I)
        Xnew(I) = XX + StepSize(I)
        F = MyFx(Xnew, N)
        If F < BestF Then
          BestF = F
          bMoved(I) = True
        Else
          Xnew(I) = XX - StepSize(I)
          F = MyFx(Xnew, N)
          If F < BestF Then
            BestF = F
            bMoved(I) = True
          Else
            Xnew(I) = XX
            Exit Do
          End If
        End If
      Loop
    Next I
    
    ' moved in any direction?
    bMadeAnyMove = True
    For I = 1 To N
      If Not bMoved(I) Then
        bMadeAnyMove = False
        Exit For
      End If
    Next I
    
    If bMadeAnyMove Then
      For I = 1 To N
        Deltax(I) = Xnew(I) - X(I)
      Next I
'''      Lambda = CubicIntMin(N, X, Deltax, 0, 1, 0.0001, 0.00001, 100)
'''      For I = 1 To N
'''        Xnew(I) = X(I) + Lambda * Deltax(I)
'''      Next I
      If LinSearch_DirectSearch(X, N, Lambda, Deltax, 0.1, 0.0001) Then
        For I = 1 To N
          Xnew(I) = X(I) + Lambda * Deltax(I)
        Next I
      End If
    End If
    BestF = MyFx(Xnew, N)
    
    ' reduce the step size for the dimensions that had no moves
    For I = 1 To N
      If Not bMoved(I) Then StepSize(I) = StepSize(I) / 2
    Next I
        
            
    ' show results
    Cells(Row, 5) = BestF
    For I = 1 To N
      Cells(Row, 5 + I) = X(I)
      Cells(Row, 5 + I + N) = StepSize(I)
    Next I
        
    ' test function value convergence
    'If Abs(BestF - LastBestF) < EPSF Then Exit Do
        
    LastBestF = BestF
    
    bStop = True
    For I = 1 To N
      If StepSize(I) >= MinStepSize(I) Then
        bStop = False
        Exit For
      End If
    Next I
    
  Loop Until bStop
  
End Sub


%}

BACK

Copyright (c) Namir Shammas. All rights reserved.