[Index for tmp_for_tar/quad_min.doc] [Return to Master Index]

quad_min

(tmp_for_tar/quad_min.doc/quad_min.m)


Function Synopsis

[xbest,vbest,niter,hbest,ybest]=quad_min(func,d2func,xinit,...)

Help text

 [x,v,niter,h,y] = quad_min(f,d2f,init,...) - Newton-like minimization

               Minimized function.          |Returns Value, 1st and 
                                  \         |2nd derivatives of func
                                   \       /      .Starting point
                                    |     |      /
                                    v     v     v
       [x,v,niter,h,y] = quad_min(func,d2func,xinit,options)
        ^ ^  ^    ^ ^
        | |  |    |  \ 
        | |  |     \  See below
        | |   \     Pseudo-inverse of Hessian
        |  \   Number of iterations
        |   Best value of "func"
 Best "x" found

 Not-quite like Newton iterations to find minimum evenberg-Marquardt method for minimizing the norm of
 func(u,x) starting from "xinit".

 "Not quite" because it minimizes a general function, given an
 implementation of the function, and of its 1st (gradient vector) and
 2nd (Hessian matrix) derivatives, while Levenberg-Marquart is for
 minimizing a sum-of-squares, given a (vector-valued) function and its
 1st derivatives.

 Somewhat like Levenberg-Marquardt in the way of avoiding the pitfall
 of Newton methods that are not garanteed to be non-increasing.

 So it's some sort of bastard optimization function ...

 Arguments :

 - xinit is a N-by-1 column vector. 

 - "func" is the cost function : v = func(u,x), or v = func(u,x,y) if
   an extra argument "y" is specified amongst the options.

 - "d2func" returns the cost (1x1), its differential (1xN) and the
   *pseudo-inverse* of its second differential (NxN) :

    [v,dv,d2v]=d2func(u,x[,y]). "y" is again optional.

 Options :

 "vinit",v     : Value of the function at xinit. Saves one evaluation.

 "maxouter", m : Max number of outer loop iterations (default : 500)

 "maxinner", m : Max number of inner loop iterations (default :  30)

 "mimprov", w  : Stop if best_value over new_best_value is above w,
                 which should be 0<w<1.              (default:0.999)

 "mingrad", w  : Stop if gradient has 2-norm smaller than w. 
                 (default : eps) 

 "y",       y  : Extra argument to func,d2func.

 "code",code   : The passed string will be evaluated after each outer
                 loop that produced some (any) improvement. "x", the
                 best parameter found, "v" the best value and
                 eventually "y" are visible from the code.



Cross-Reference Information

This function calls

Listing of function file tmp_for_tar/quad_min.doc/quad_min.m

## [x,v,niter,h,y] = quad_min(f,d2f,init,...) - Newton-like minimization
## 
##               Minimized function.          |Returns Value, 1st and 
##                                  \         |2nd derivatives of func
##                                   \       /      .Starting point
##                                    |     |      /
##                                    v     v     v
##       [x,v,niter,h,y] = quad_min(func,d2func,xinit,options)
##        ^ ^  ^    ^ ^
##        | |  |    |  \ 
##        | |  |     \  See below
##        | |   \     Pseudo-inverse of Hessian
##        |  \   Number of iterations
##        |   Best value of "func"
## Best "x" found
##
## Not-quite like Newton iterations to find minimum evenberg-Marquardt method for minimizing the norm of
## func(u,x) starting from "xinit".
##
## "Not quite" because it minimizes a general function, given an
## implementation of the function, and of its 1st (gradient vector) and
## 2nd (Hessian matrix) derivatives, while Levenberg-Marquart is for
## minimizing a sum-of-squares, given a (vector-valued) function and its
## 1st derivatives.
##
## Somewhat like Levenberg-Marquardt in the way of avoiding the pitfall
## of Newton methods that are not garanteed to be non-increasing.
##
## So it's some sort of bastard optimization function ...
## 
## Arguments :
##
## - xinit is a N-by-1 column vector. 
##
## - "func" is the cost function : v = func(u,x), or v = func(u,x,y) if
##   an extra argument "y" is specified amongst the options.
##
## - "d2func" returns the cost (1x1), its differential (1xN) and the
##   *pseudo-inverse* of its second differential (NxN) :
##
##    [v,dv,d2v]=d2func(u,x[,y]). "y" is again optional.
##
## Options :
##
## "vinit",v     : Value of the function at xinit. Saves one evaluation.
##
## "maxouter", m : Max number of outer loop iterations (default : 500)
##
## "maxinner", m : Max number of inner loop iterations (default :  30)
##
## "mimprov", w  : Stop if best_value over new_best_value is above w,
##                 which should be 0<w<1.              (default:0.999)
##
## "mingrad", w  : Stop if gradient has 2-norm smaller than w. 
##                 (default : eps) 
##
## "y",       y  : Extra argument to func,d2func.
##
## "code",code   : The passed string will be evaluated after each outer
##                 loop that produced some (any) improvement. "x", the
##                 best parameter found, "v" the best value and
##                 eventually "y" are visible from the code.
##
## Author : Etienne Grossmann <etienne@isr.ist.utl.pt>
##
function [xbest,vbest,niter,hbest,ybest]=quad_min(func,d2func,xinit,...)

## Sometimes I suspect modified sources are not recompiled. This
## static variable is displayed each time this func is called, and
## should change at (almost) each recompilation.

## static dummy_levmar = floor(100*rand());
## dummy_levmar 

# Set the defaults (not all) #########################################
vinit = nan ;			# maximum distance

maxouter = 500 ;			
maxinner = 30 ;
mimprov = 0.999 ;
mingrad = eps ;

tcoeff = 0.5 ;			# Discount on total weight
ncoeff = 0.5 ;			# Discount on weight of newton
ocoeff = 1.5 ;			# Factor for outwards searching

report = 0 ;			# Never report
verbose = 0 ;			# Be quiet
prudent = 0 ;			# Check coherence of d2func and func?

niter = 0 ;
neval = 0 ;

code = "" ;
## d2func = dfunc = 0 ;

# ####################################################################
# Read the options ###################################################
# ####################################################################
# Options with a value
opt1 = " vinit maxouter maxinner report mimprov mingrad code y " ;
# Boolean options 
opt0 = " verbose prudent " ;

va_start() ;
nargin = nargin - 3 ;
while nargin>0 ,
  tmp = va_arg() ; nargin-- ;
  if ! isstr(tmp) ,
    break			# Last option has been read. "tmp" is
				# first arg.
  end
  if index(opt1,[" ",tmp," "]) ,
    
    tmp2 = va_arg() ; nargin-- ;
    ## nargin-- ;
    eval([tmp,"=tmp2;"]) ;

    sayif(verbose ,"quad_min : Read option : %s.\n",tmp) ;

  elseif index(opt0,[" ",tmp," "]) ,
    
    eval([tmp,"=1;"]) ;
    sayif(verbose ,"quad_min : Read boolean option : %s\n",tmp) ;

  else
    printf("quad_min : Unknown option : %s\n",tmp) ;
    keyboard
  end
endwhile

############################## Checking ##############################
if mimprov<=0 || mimprov>=1,
  printf("quad_min : mimprov=%8.3g is not in ]0,1[ \n",mimprov) ;
  keyboard
end

if !isstr (d2func) || !isstr (func),
  printf("quad_min : I need func and d2func to be strings!\n");
  keyboard
end

x = xinit ;
N = prod (size (x)) ;
x = reshape (x, N, 1) ;


exist_y = exist ("y","var");
if isnan (vinit) , 
  if exist_y, v = feval (func, x, y); ybest = y;
  else        v = feval (func, x);  
  end
else          v = vinit ; 
end
## keyboard

xbest = x ;
vold = vbest = nan ;
hbest = nan ;

sayif( verbose,"quad_min : Initially, v=%8.3g\n",v);

while niter++ <= maxouter ,

  if exist_y, [v,d,h] = feval(d2func,x,y) ;
  else        [v,d,h] = feval(d2func,x) ;
  end

  if prudent,
    if exist_y, v2 = feval(func,x,y) ;
    else        v2 = feval(func,x) ;
    end
    if abs(v2-v)>0.001*sqrt(eps),
      printf("quad_min : func and d2func disagree %8.3g\n",abs(v2-v));
      keyboard
    end
  end
  xbest = x ;
  vold = vbest = v ;
  hbest = h ;
  if exist_y, ybest = y; end

  ## printf("vold=%8.3g , v=%8.3g *****************************\n",vold,v);
  
  sayif( verbose || report && (rem(niter,max(report,1)) == 1) ,...
	"quad_min : niter=%d, v=%8.3g\n",niter,v ); 
  wn = 1 ;			# Weight of Newton step
  wt = 1 ;			# Total weight

  if msq(d) < mingrad,
    sayif( verbose || report ,...
	  "quad_min : exiting 'cause low gradient\n");
    ## keyboard
    break			# Exit outer loop
  end

  dnewton = -h*d' ;
  done_inner = 0;		# 0=not found. 1=Ready to quit inner.

  ninner = 0 ;
  while ninner++ < maxinner,	# Inner loop #########################
		       
    dx = wt*(wn*dnewton - (1-wn)*d') ;
    xnew = x+dx ;

    sayif( verbose, ...
	  ["Weight : total=%8.3g, newtons's=%8.3g  vbest=%8.3g ",...
	   "Norm:Newton=%8.3g, deriv=%8.3g\n"],...
	  wt,wn,vbest,norm(wt*wn*dnewton),norm(wt*(1-wn)*d'));
    
    if any(isnan(xnew)),
      printf("quad_min : Whoa!! any(isnan(xnew)) (1)\n"); 
      keyboard
    end
    
    if exist_y, vnew = feval (func, xnew, y); 
    else        vnew = feval (func, xnew); 
    end

    neval++ ;
    if vnew<vbest ,
      dbest = dx ; vbest = vnew; xbest = xnew; 
      done_inner = 1 ;		# Will go out at next increase
      sayif( verbose,"quad_min : going down\n" );
      
    elseif done_inner == 1,	# Time to go out
      sayif( verbose,"quad_min : quitting %d th inner loop\n",niter); 
      break			# out of inner loop
    end
    wt = wt*tcoeff ;
    wn = wn*ncoeff ;
  end				# End of inner loop ##################

  if ninner >= maxinner ,	# There was a problem
    sayif(verbose, "quad_min : inner looping forever (vnew=%8.3g)\n",vnew);

  else				# Look for improvement along dbest
    wn = 1.5 ; 
    xnew = x+wn*dbest;
    if any(isnan(xnew)),
      printf("quad_min : Whoa!! any(isnan(xnew)) (1)\n"); 
      keyboard
    end
    if exist_y, vnew = feval (func, xnew, y) ; 
    else        vnew = feval (func, xnew) ; 
    end

    while vnew < vbest,
      vbest = vnew; xbest = xnew; 
      wn = wn*ocoeff ;
      xnew = x+wn*dbest;
      if exist_y, vnew = feval (func, xnew, y); 
      else        vnew = feval (func, xnew); 
      end
    end
  end				# End of improving along dbest

  if verbose || rem(niter,max(report,1)) == 1,
    if vold,
      sayif(verbose, "quad_min : done inner vbest=%8.5g, vbest/vold=%8.5g\n",...
	     vbest,vbest/vold);
    else
      sayif(verbose, "quad_min : done inner vbest=%8.5g, vold=0\n",...
	     vbest);
    end
  end
  if vbest < vold ,
    ## "improvement found"
    if prudent,
      if exist_y, tmpv = feval (func, xbest, y) ; 
      else        tmpv = feval (func, xbest) ; 
      end
      if abs(tmpv-vbest)>eps,
	printf("quad_min : Whoa! best value is changing\n");
	keyboard
      end
    end
    v = vbest; x = xbest;
    if ! isempty (code),
      sayif (verbose,"quad_min : Gonna eval("%s"\n",code); 
      eval (code);
      xbest = x; 
      if exist_y, ybest = y; end
      if prudent,
	tmpv = feval (func, x, y);
	if abs (tmpv-vbest) > eps,
	  printf("quad_min : Whoa! best value changes after eval(code)\n");
	  keyboard
	end
      end
    end
  end

  if vbest > mimprov*vold , 
    if verbose || report ,
      printf("quad_min : quitting, niter=%-3d v=%8.3g, ",niter,v);
      if vold, printf("v/vold=%8.3g \n",v/vold);
      else     printf("vold  =0     \n",v);
      end
    end
    ## keyboard
    break ;			# out of outer loop
  end   
end				# End of outer loop ##################

if niter >= maxouter ,
  sayif(verbose, "quad_min : outer looping forever\n");
end

if exist_y, err = feval (func, xbest, ybest); 
else        err = feval (func, xbest); 
end

if abs (err-vbest) > eps,
  printf("quad_min : Whoa!! xbest does not eval to vbest\n");
  printf("         : %8.3e - %8.3e = %8.3e != 0\n",err,vbest,err-vbest);
  keyboard
end

Produced by oct2html on Tue Oct 10 18:28:41 2000
Cross-Directory links are: ON