Dear Olaf,

Thank you for your suggestions.

> - Why is 'h' randomized? Even if there should be a good reason, I think this
> cannot be done inside 'line_min'. Rather, make 'h' configurable so that users
> can randomize it 'from outside'.

Since h is currently set arbitrarily, I have found for my applications
that randomizing it somewhat is helpful in optimization (where
line_min is typically called repeatedly), because it is always
possible that for a particular function the hard-coded value will not
lead to downhill movement.

Another possible fix would be, as you say, to make the step size h
configurable. I added the ability for users to provide h as an input.

> - Are you sure you don't break someones code by limiting number of evaluations
> to 30? Shouldn't this rather be made configurable, too?

I added the maximum number of evaluations as another optional input.

> - I think you should only list those changes in the comments which actually
> are made to the code in SVN now.

I fixed the description of my changes. The diff file shows the changes
in my version from the current SVN version.

> - Minor issue: The preferred style of Octave is leaving a space between
> fuction name and parantheses (e.g. sum ()) (you have deleted the space at
> some point(s)).

Modified accordingly.

Best,

Nir
13c13
< ## [a,fx,nev] = line_min (f, dx, args, narg) - Minimize f() along dx
---
> ## [a,fx,nev] = line_min (f, dx, args, narg, h, nev_max) - Minimize f() along 
> dx
18c18
< ## args : list    : List of argument of f
---
> ## args : cell    : Arguments of f
19a20,21
> ## h    : scalar  : Step size to use for centered finite difference 
> approximation of first and second derivatives. Default=around 1E-3 (exact 
> value randomized between calls)
> ## nev_max : integer : Maximum number of function evaluations.  Default=30
22,23c24,25
< ## a    : scalar  : Value for which f(x+a*dx) is a minimum (*)
< ## fx   : scalar  : Value of f(x+a*dx) at minimum (*)
---
> ## a    : scalar  : Value for which f(x+a*dx) is a minimum
> ## fx   : scalar  : Value of f(x+a*dx) at minimum
26d27
< ## (*) The notation f(x+a*dx) assumes that args == list (x).
42c43,49
< function [a,fx,nev] = line_min (f, dx, args, narg)
---
> ## 2011-11-27 Nir Krakauer
> ## * randomized the step size h
> ## * modified to limit the number of function evaluations
> ## * added both h and the number of function evaluations as optional inputs
> ## * added a check to ensure that the function value returned was never more 
> than the initial value
>
> function [a,fx,nev] = line_min (f, dx, args, narg, h, nev_max)
47a55,60
>   if nargin < 5 || ~isnumeric(h), h = exp(rand() - 0.5)*0.001;        end 
>   #previously h = 1E-3 or 1E-2
>
>   if nargin < 6 || ~isnumeric(nev_max), nev_max = 30; end
>
>
49c62
<   h = 0.001;                  # Was 0.01 here
---
>   
52,53c65,68
<                               # was 1e-4
<   while (abs (velocity) > 0.000001)
---
>
>   min_velocity_change = 0.000001; # was 1e-4
>                               
>   while (abs (velocity) > min_velocity_change) && (nev < nev_max)
56a72,74
>     if nev == 0
>       fx0 = fx;
>     end
65a84,95
>   
>   fx = feval (f,args{1:narg-1}, x+a*dx, args{narg+1:end});
>   nev++;
>   if fx >= fx0 %if no improvement, return the starting value
>       a = 0;
>       fx = fx0;
>   end
>   
>   if (nev >= nev_max)
>       disp('line_min: maximum number of function evaluations exceeded')
>   end
>   
69c99
< ## correspond to (nearly) optimal fx.
\ No newline at end of file
---
> ## correspond to (nearly) optimal fx.
## Copyright (C) 2000 Ben Sapp.  All rights reserved.
##
## This program is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by the
## Free Software Foundation; either version 2, or (at your option) any
## later version.
##
## This is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
## for more details.

## [a,fx,nev] = line_min (f, dx, args, narg, h, nev_max) - Minimize f() along dx
##
## INPUT ----------
## f    : string  : Name of minimized function
## dx   : matrix  : Direction along which f() is minimized
## args : cell    : Arguments of f
## narg : integer : Position of minimized variable in args.  Default=1
## h    : scalar  : Step size to use for centered finite difference approximation of first and second derivatives. Default=around 1E-3 (exact value randomized between calls)
## nev_max : integer : Maximum number of function evaluations.  Default=30
##
## OUTPUT ---------
## a    : scalar  : Value for which f(x+a*dx) is a minimum
## fx   : scalar  : Value of f(x+a*dx) at minimum
## nev  : integer : Number of function evaluations
##

## Author: Ben Sapp <bs...@lanl.gov>
## Reference: David G Luenberger's Linear and Nonlinear Programming
##
## Changelog : -----------
## 2002-01-28 Paul Kienzle
## * save two function evaluations by inlining the derivatives
## * pass through varargin{:} to the function
## 2002-03-13 Paul Kienzle
## * simplify update expression
## 2002-04-17 Etienne Grossmann <etie...@isr.ist.utl.pt>
## * Rename nrm.m to line_min.m (in order not to break dfp, which uses nrm)
## * Use list of args, suppress call to __pseudo_func__
## * Add nargs argument, assume args is a list
## * Change help text
## 2011-11-27 Nir Krakauer
## * randomized the step size h
## * modified to limit the number of function evaluations
## * added both h and the number of function evaluations as optional inputs
## * added a check to ensure that the function value returned was never more than the initial value

function [a,fx,nev] = line_min (f, dx, args, narg, h, nev_max)
  velocity = 1;
  acceleration = 1;

  if nargin < 4, narg = 1; end

  if nargin < 5 || ~isnumeric(h), h = exp(rand() - 0.5)*0.001;	end 
  #previously h = 1E-3 or 1E-2

  if nargin < 6 || ~isnumeric(nev_max), nev_max = 30;	end


  nev = 0;
  
  x = args{narg};
  a = 0;

  min_velocity_change = 0.000001; # was 1e-4
				
  while (abs (velocity) > min_velocity_change) && (nev < nev_max)
    fx = feval (f,args{1:narg-1}, x+a*dx, args{narg+1:end});
    fxph = feval (f,args{1:narg-1}, x+(a+h)*dx, args{narg+1:end});
    fxmh = feval (f,args{1:narg-1}, x+(a-h)*dx, args{narg+1:end});
    if nev == 0
    	fx0 = fx;
    end

    velocity = (fxph - fxmh)/(2*h);
    acceleration = (fxph - 2*fx + fxmh)/(h^2);
    if abs(acceleration) <= eps, acceleration = 1; end # Don't do div by zero
				# Use abs(accel) to avoid problems due to
				# concave function
    a = a - velocity/abs(acceleration);
    nev += 3;
  endwhile
  
  fx = feval (f,args{1:narg-1}, x+a*dx, args{narg+1:end});
  nev++;
  if fx >= fx0 %if no improvement, return the starting value
  	a = 0;
	fx = fx0;
  end
  
  if (nev >= nev_max)
  	disp('line_min: maximum number of function evaluations exceeded')
  end
  
endfunction

## Rem : Although not clear from the code, the returned a always seems to
## correspond to (nearly) optimal fx.
------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure 
contains a definitive record of customers, application performance, 
security threats, fraudulent activity, and more. Splunk takes this 
data and makes sense of it. IT sense. And common sense.
http://p.sf.net/sfu/splunk-novd2d
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to