Hi All,

I have created and modified two algorithms.
One of them is the nonlinear conjugate gradient explained on the
wiki page. The code is based on Etienne Grossmann code however
I had to modify it seriously.
Now it is in sync with the wikipedia page description.

There are two comments I have to make.
Etienne said that BGFS method works better in many cases 
which for this reason is already called in
fmins and fsearchmin functions. 
These algorithms do not rely on analytical derivatives
which may or many not be an advantage.

The cg_min function I provided requires analytical derivatives and the main 
purpose to provide it is to have it since many articles do performance studies 
with
nonlin conjgrad.

The other algo of mine is written from scratch.
It gives the confidence level of being a multinomial distribution well 
represented by
the sampling portions (ie. within predefined confidence intervals ).
It considers finite population and infinite populations as well.

Please give comments on my functions and let me put in the repository.

Levente

optim package:

cg_min.m
bracket_min.m
brent_line_min.m
semi_bracket.m

statistics package:

cl_multinom.m

Thanks:

Levente


-- 
Blogger of http://fapuma.blogspot.com
Pictures of my life at http://picasaweb.google.com/TorokLev
In addition: http://www.youtube.com/watch?v=0CUDg3NPEXY&fmt=16

-------------------------------------------------------

-- 
Blogger of http://fapuma.blogspot.com
## -*- texinfo -*-
## @deftypefn {Function File} {...@var{s},@var{v},@var{n}]} brent_line_min ( @var{f},@var{df},@var{args},@var{ctl} )
## Line minimization of f along df
##
## Finds minimum of f on line @math{ x0 + dx*w | a < w < b } by
## bracketing. a and b are passed through argument ctl.
##
## @subheading Arguments
## @itemize @bullet
## @item @var{f}     : string : Name of function. Must return a real value
## @item @var{args}  : cell   : Arguments passed to f or RxC    : f's only argument. x0 must be at @var{ar...@{ @var{ctl}(2) @}
## @item @var{ctl}   : 5      : (optional) Control variables, described below.
## @end itemize
## 
## @subheading Returned values
## @itemize @bullet
## @item @var{s}   : 1        : Minimum is at x0 + s*dx
## @item @var{v}   : 1        : Value of f at x0 + s*dx
## @item @var{nev} : 1        : Number of function evaluations
## @end itemize
##
## @subheading Control Variables
## @itemize @bullet
## @item @var{ctl}(1)       : Upper bound for error on s              Default=sqrt(eps)
## @item @var{ctl}(2)       : Position of minimized argument in args  Default= 1
## @item @var{ctl}(3)       : Maximum number of function evaluations  Default= inf
## @item @var{ctl}(4)       : a                                       Default=-inf
## @item @var{ctl}(5)       : b                                       Default= inf
## @end itemize
##
## Default values will be used if ctl is not passed or if nan values are
## given.
## @end deftypefn


function [s,gs,nev] = brent_line_min( f,dx,args,ctl )

verbose = 0;

seps = sqrt (eps);

				# Default control variables
tol = 10*eps; # sqrt (eps); 
narg = 1;
maxev = inf;
a = -inf;
b = inf;

if nargin >= 4,			# Read arguments
  if !isnan (ctl (1)), tol = ctl(1); end
  if length (ctl)>=2 && !isnan (ctl(2)), narg = ctl(2); end
  if length (ctl)>=3 && !isnan (ctl(3)), maxev = ctl(3); end
  if length (ctl)>=4 && !isnan (ctl(4)), a = ctl(4); end
  if length (ctl)>=5 && !isnan (ctl(5)), b = ctl(5); end

end				# Otherwise, use defaults, def'd above

if a>b, tmp=a; a=b; b=tmp; end

if narg > length (args),
  printf ("brent_line_min : narg==%i > length (args)==%i",\
    narg, length (args));
  keyboard
end


if ! iscell (args), 
	args = {args}; 
endif

x = args{ narg };

[R,C] = size (x);
N = R*C;			# Size of argument

gs0 = gs = feval (f, args);
nev = 1;
				# Initial value
s = 0;

if all (dx==0), return; end	# Trivial case

				# If any of the bounds is infinite, find
				# finite bounds that bracket minimum
if !isfinite (a) || !isfinite (b),
  if !isfinite (a) && !isfinite (b),
    [a,b, ga,gb, n] = bracket_min (f, dx, narg, args);
  elseif !isfinite (a),
    [a,b, ga,gb, n] = semi_bracket (f, -dx, -b, narg, args);
    tmp = a;  a = -b; b = -tmp;
    tmp = ga; ga = gb; gb = tmp;
  else
    [a,b, ga,gb, n] = semi_bracket (f,  dx, a, narg, args);
  end
  nev += n;
else
  args{narg} = x+a*dx; 	ga = feval( f, args );
  args{narg} = x+b*dx;  gb = feval( f, args );
  nev += 2;
end				# End of finding bracket for minimum

if a > b,			# Check assumptions
  printf ("brent_line_min : a > b\n");
  keyboard
end

s = 0.5*(a+b);
args{narg} = x+ s*dx; gs = feval( f, args );
end
nev++;

if verbose,
  printf ("[a,s,b]=[%.3e,%.3e,%.3e], [ga,gs,gb]=[%.3e,%.3e,%.3e]\n",\
	  a,s,b,ga,gs,gb);
end

maxerr = 2*tol;

while ( b-a > maxerr ) && nev < maxev,

  if gs > ga && gs > gb,	# Check assumptions
    printf ("brent_line_min : gs > ga && gs > gb\n");
    keyboard
  end
  
  if ga == gb && gb == gs, break end

				# Don't trust poly_2_ex for glued points
				# (see test_poly_2_ex).

  ## if min (b-s, s-a) > 10*seps,

				# If s is not glued to a or b and does not
				# look linear 
  ## mydet = sum (l([2 3 1]).*f([3 1 2])-l([3 1 2]).*f([2 3 1]))
  mydet = sum ([s b a].*[gb ga gs] - [b a s].*[gs gb ga]);
  if min (b-s, s-a) > 10*seps && abs (mydet) > 10*seps && \
	(t = poly_2_ex ([a,s,b], [ga, gs, gb])) < b && t > a,

				# t has already been set

    ## if t>=b || t<=a,
    ##  printf ("brent_line_min : t is not in ]a,b[\n");
    ##  keyboard
    ## end

				# Otherwise, reduce the biggest of the
				# intervals, but not too much
  elseif s-a > b-s,
    t = max (0.5*(a+s), s-100*seps);
  else
    t = min (0.5*(s+b), s+100*seps);
  end

  if abs (t-s) < 0.51*maxerr,
    #sayif (verbose, "ungluing t and s\n");
    t = s + (1 - 2*(s-a > b-s))*0.49*maxerr ; 
  end

  if a > s || s > b,		# Check assumptions
    printf ("brent_line_min : a > s || s > b\n");
    keyboard
  end

  xt = args;
  args{narg} = x+t*dx;
  gt = feval( f, args );
  nev++;

  if verbose,
    printf ("t = %.3e, gt = %.3e\n",t,gt);
  end

  if t<s,			# New point is in ]a,s[

    if gt > ga + seps,		# Check assumptions
      printf ("brent_line_min : gt > ga\n");
      keyboard
    end

    if gt < gs,
      b = s; gb = gs;
      s = t; gs = gt;
    else
      a = t; ga = gt;
    end
  else				# New point is in ]s,b[
    if gt > gb + seps,		# Check assumptions
      printf ("brent_line_min : gt > gb\n");
      keyboard
    end

    if gt < gs,
      a = s; ga = gs;
      s = t; gs = gt;
    else
      b = t; gb = gt;
    end
  end

  if verbose,
    printf ("[a,s,b]=[%.3e,%.3e,%.3e], [ga,gs,gb]=[%.3e,%.3e,%.3e]\n",\
	    a,s,b,ga,gs,gb);
  end
  ## keyboard
  ## [b-a, maxerr]
end

s2 = 0.5*(a+b);
args{narg} = x + s2*dx; gs2 = feval (f, args );
nev++;

if gs2 < gs,
  s = s2; gs = gs2;
end

if gs > gs0,
  printf ("brent_line_min : goes uphill by %8.3e\n",gs-gs0);
  keyboard
end
## [a, b, ga, gb, nev] = semi_bracket (f, dx, a, narg, args)
##
## Find an interval containing a local minimum of the function 
## g : h in reals ---> f (x+h*dx) where x = args{narg}
##
## a < b.
## nev is the number of function evaluations

## Author : Etienne Grossmann <etie...@isr.ist.utl.pt>
## Modified by: Levente Torok <torok...@gmail.com>
## This software is distributed under the terms of the GPL

function [a, b, ga, gb, n] = bracket_min (f, dx, narg, args)

[a,b, ga,gb, n] = semi_bracket (f, dx, 0, narg, args);

if a != 0, return; end

[a2,b2, ga2,gb2, n2] = semi_bracket (f, -dx, 0, narg, args);

n += n2;

if a2 == 0,
  a = -b2; ga = gb2;
else
  a = -b2; b = -a2; ga = gb2; gb = ga2; 
end

## -*- texinfo -*-
## @deftypefn {Function File} {...@var{x0},@var{v},@var{nev}]} cg_min ( @var{f},@var{df},@var{args},@var{ctl} )
## NonLinear Conjugate Gradient method to minimize function @var{f}.
##
## @subheading Arguments
## @itemize @bullet
## @item @var{f}   : string   : Name of function. Return a real value 
## @item @var{df}  : string   : Name of f's derivative. Returns a (R*C) x 1 vector 
## @item @var{args}: cell     : Arguments passed to f...@*
## @item @var{ctl}   : 5-vec    : (Optional) Control variables, described below
## @end itemize
##
## @subheading Returned values
## @itemize @bullet
## @item @var{x0}    : matrix   : Local minimum of f
## @item @var{v}     : real     : Value of f in x0
## @item @var{nev}   : 1 x 2    : Number of evaluations of f and of df
## @end itemize
##
## @subheading Control Variables
## @itemize @bullet
## @item @var{ctl}(1)       : 1 or 2 : Select stopping criterion amongst :
## @item @var{ctl}(1)==0    : Default value
## @item @var{ctl}(1)==1    : Stopping criterion : Stop search when value doesn't
## improve, as tested by @math{ ctl(2) > Deltaf/max(|f(x)|,1) }
## where Deltaf is the decrease in f observed in the last iteration
## (each iteration consists R*C line searches).
## @item @var{ctl}(1)==2    : Stopping criterion : Stop search when updates are small,
## as tested by @math{ ctl(2) > max { dx(i)/max(|x(i)|,1) | i in 1..N }}
## where  dx is the change in the x that occured in the last iteration.
## @item @var{ctl}(2)       : Threshold used in stopping tests.           Default=10*eps
## @item @var{ctl}(2)==0    : Default value
## @item @var{ctl}(3)       : Position of the minimized argument in args  Default=1
## @item @var{ctl}(3)==0    : Default value
## @item @var{ctl}(4)       : Maximum number of function evaluations      Default=inf
## @item @var{ctl}(4)==0    : Default value
## @item @var{ctl}(5)       : Type of optimization:
## @item @var{ctl}(5)==1    : "Fletcher-Reves" method
## @item @var{ctl}(5)==2    : "Polak-Ribiere" (Default)
## @item @var{ctl}(5)==3    : "Hestenes-Stiefel" method
## @end itemize
##
## @var{ctl} may have length smaller than 4. Default values will be used if ctl is
## not passed or if nan values are given.
## @subheading Example:
##
## function r=df( l )  b=[1;0;-1]; r = -( 2...@{1@} - 2*b + rand(size(l{1}))); endfunction @*
## function r=ff( l )  b=[1;0;-1]; r = (l...@{1@}-b)' * (l...@{1@}-b); endfunction @*
## ll = @{ [10; 2; 3] @}; @*
## ctl(5) = 3; @*
## [x0,v,nev]=cg_min( "ff", "df", ll, ctl ) @*
## 
## Comment:  In general, BFGS method seems to be better performin in many cases but requires more computation per iteration
## @seealso{ bfgsmin, http://en.wikipedia.org/wiki/Nonlinear_conjugate_gradient }
## @end deftypefn

## Author : Etienne Grossmann <etie...@isr.ist.utl.pt>
## Modified by: Levente Torok <torok...@gmail.com>
## This software is distributed under the terms of the GPL

function [x,v,nev] = cg_min (f, dfn, args, ctl)

verbose = 0;

crit = 1;			# Default control variables
tol = 10*eps;
narg = 1;
maxev = inf;
method = 2;

if nargin >= 4,			# Read arguments
  if                    !isnan (ctl(1)) && ctl(1) ~= 0, crit  = ctl(1); end
  if length (ctl)>=2 && !isnan (ctl(2)) && ctl(2) ~= 0, tol   = ctl(2); end
  if length (ctl)>=3 && !isnan (ctl(3)) && ctl(3) ~= 0, narg  = ctl(3); end
  if length (ctl)>=4 && !isnan (ctl(4)) && ctl(4) ~= 0, maxev = ctl(4); end
  if length (ctl)>=5 && !isnan (ctl(5)) && ctl(5) ~= 0, method= ctl(5); end
end

if iscell (args),		# List of arguments 
  x = args{narg};
else					# Single argument
  x = args;
  args = {args};
end

if narg > length (args),	# Check
  error ("cg_min : narg==%i, length (args)==%i\n",
	 narg, length (args));
end

[R, C] = size(x);
N = R*C;
x = reshape (x,N,1) ;

nev = [0, 0];

v = feval (f, args);
nev(1)++;

dxn = lxn = dxn_1 = -feval( dfn, args );
nev(2)++;

done = 0;

## TEMP
## tb = ts = zeros (1,100);

				# Control params for line search
ctlb = [10*sqrt(eps), narg, maxev];
if crit == 2, ctlb(1) = tol; end

x0 = x;
v0 = v;

nline = 0;
while nev(1) <= maxev ,
  ## xprev = x ;
  ctlb(3) = maxev - nev(1);	# Update # of evals


  ## wiki alg 4.
  [alpha, vnew, nev0] = brent_line_min (f, dxn, args, ctlb);

  nev += nev0;
  ## wiki alg 5.
  x = x + alpha * dxn;

  if nline >= N,
    if crit == 1,
      done = tol > (v0 - vnew) / max (1, abs (v0));
    else
      done = tol > norm ((x-x0)(:));
    end
    nline = 1;
    x0 = x;
    v0 = vnew;
  else
    nline++;
  end
  if done || nev(1) >= maxev,  return  end
  
  if vnew > v + eps ,
    printf("cg_min: step increased cost function\n");
    keyboard
  end
  
  # if abs(1-(x-xprev)'*dxn/norm(dxn)/norm(x-xprev))>1000*eps,
  #  printf("cg_min: step is not in the right direction\n");
  #  keyboard
  # end
  
  # update x at the narg'th position of args cellarray
  args{narg} = reshape (x, R, C);

  v = feval (f, args);
  nev(1)++;

  if verbose, printf("cg_min : nev=%4i, v=%8.3g\n",nev(1),v) ; end

  ## wiki alg 1:
  dxn = -feval (dfn, args);
  nev(2)++;

  # wiki alg 2:
  switch method
  
    case 1 # Fletcher-Reenves method
	  nu = dxn' * dxn;
      de  = dxn_1' * dxn_1;

    case 2 # Polak-Ribiere method
      nu = (dxn-dxn_1)' * dxn;
      de  = dxn_1' * dxn_1;

    case 3 # Hestenes-Stiefel method
      nu = (dxn-dxn_1)' * dxn;
	  de  = (dxn-dxn_1)' * lxn;

	otherwise
      error("No method like this");

  endswitch

  if nu == 0,
  	return
  endif
  
  if de == 0,
    error("Numerical instability!");
  endif
  beta = nu / de;
  beta = max( 0, beta );
  ## wiki alg 3.   update dxn, lxn, point 
  dxn_1 = dxn;
  dxn = lxn = dxn_1 + beta*lxn ;

end

if verbose, printf ("cg_min: Too many evaluatiosn!\n"); end

endfunction

## [a, b, ga, gb, nev] = semi_bracket (f, dx, a, narg, args)
##
## Find an interval containing a local minimum of the function 
## g : h in [a, inf[ ---> f (x+h*dx) where x = nth (args, narg)
##
## The local minimum may be in a.
## a < b.
## nev is the number of function evaluations.

## Author : Etienne Grossmann <etie...@isr.ist.utl.pt>
## Modified by: Levente Torok <torok...@gmail.com>
## This software is distributed under the terms of the GPL

function [a,b,ga,gb,n] = semi_bracket (f, dx, a, narg, args)

step = 1;

x = nth (args, narg);
args{narg} =  x+a*dx; ga = feval (f, args );
b = a + step;
args{narg} =  x+b*dx; gb = feval (f, args );
n = 2;

if gb >= ga, return ; end

while 1,

  c = b + step;
  args{narg} = x+c*dx; gc = feval( f, args );
  n++;

  if gc >= gb,			# ga >= gb <= gc
    gb = gc; b = c;
    return;
  end
  step *= 2;
  a = b; b = c; ga = gb; gb = gc;
end
# -*- texinfo -*-
#
# @deftypefn {Function File} {...@var{cl}} cl_multinom( @var{x},@var{N},@var{b},@var{calculation_type} ) - Confidence level of multinomial portions
#    Returns confidence level of multinomial parameters estimated @math{ p = x / sum x } with confidence interval @var{b}.
#    Finite population is also considered.
#
# @subheading Arguments
# @itemize @bullet
# @item @var{x}  : int vector  : sample frequencies bins
# @item @var{N}  : int         : Population size that was sampled by x. If N<sum(x), infinite number assumed
# @item @var{b}  : real, vector :  confidence interval
#            if vector, it should be the size of x containing confence interval for each cells
#            if scalar, each cell will have the same value of b unless it is zero or -1
#            if value is 0, b=.02 is assumed which is standard choice at elections
#            otherwise it is calculated in a way that one sample in a cell alteration defines the confidence interval
# @item @var{calculation_type}  : string    : (Optional), described below
# 			"bromaghin" 	(default) - do not change it unless you have a good reason to do so
# 			"cochran"
#			"agresti_cull"  this is not exactly the solution at reference given below but an adjustment of the solutions above
# @end itemize
#
# @subheading Returns
#   Confidence level.
#
# @subheading Example
#   CL = cl_multinom( [27;43;19;11], 10000, 0.05 )
#     returns 0.69 confidence level.
#
# @subheading References
#
# "bromaghin" calculation type (default) is based on
# is based on the article
#   Jeffrey F. Bromaghin, "Sample Size Determination for Interval Estimation of Multinomial Probabilities", The American Statistician  vol 47, 1993, pp 203-206.
#
# "cochran" calculation type
# is based on article
#   Robert T. Tortora, "A Note on Sample Size Estimation for Multinomial Populations", The American Statistician, , Vol 32. 1978,  pp 100-102.
#
# "agresti_cull" calculation type
# is based on article in which Quesenberry Hurst and Goodman result is combined
#   A. Agresti and B.A. Coull, "Approximate is better than \"exact\" for interval estimation of binomial portions", The American Statistician, Vol. 52, 1998, pp 119-126
#
# @end deftypefn


# Copyright (C) 2009 Levente Torok / torok...@gmail.com 
# 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 of the License, or
# (at your option) any later version.^
#
# This program 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.
#
# You should have received a copy of the GNU General Public License"
# along with this program; If not, see <http://www.gnu.org/licenses/>. 
#

function CL = cl_multinom( x, N, b, calculation_type )

	k = rows(x);
	nn = sum(x);
	p = x / nn;

    if (nargin < 3)
        b = .05;
    endif
	if (isscalar( b ))
        if (b==0) b=0.02; endif
		b = ones( rows(x), 1 ) * b;	
     
        if (b<0)  b=1 ./ max( x, 1 ); endif        
	endif
	bb = b .* b;
	
    if (N==nn)
        CL = 1;
        return;
    endif
	
	if (N<nn)
		fpc = 1;
	else
		fpc = (N-1) / (N-nn); # finite population correction tag
	endif

	beta = p.*(1-p);

    if ( nargin < 4 )
        calculation_type = "bromaghin";
    endif

    switch calculation_type
      case {"cochran"}
        t = sqrt( fpc * nn * bb ./ beta )
		alpha = ( 1 - normcdf( t )) * 2

      case {"bromaghin"}
        t = sqrt(  fpc * (nn * 2 * bb )./ ( beta - 2 * bb + sqrt( beta .* beta - bb .* ( 4*beta - 1 ))) );
        alpha = ( 1 - normcdf( t )) * 2;

	  case {"agresti_cull"}
        ts = fpc * nn * bb ./ beta ;
	    if ( k<=2 )
          alpha = 1 - chi2cdf( ts, k-1 ); % adjusted Wilson interval
		else
		  alpha = 1 - chi2cdf( ts/k, 1 ); % Goodman interval with Bonferroni argument
		endif
    endswitch
 
	CL = 1 - max( alpha );

endfunction
------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
Octave-dev mailing list
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to