[fhat,xhat,ghat,Hhat,itct,fcount,retcodehat] = csminwel(fcn,x0,H0,grad,crit,nit,varargin) fcn: string naming the objective function to be minimized x0: initial value of the parameter vector H0: initial value for the inverse Hessian. Must be positive definite. grad: Either a string naming a function that calculates the gradient, or the null matrix. If it's null, the program calculates a numerical gradient. In this case fcn must be written so that it can take a matrix argument and produce a row vector of values. crit: Convergence criterion. Iteration will cease when it proves impossible to improve the function value by more than crit. nit: Maximum number of iterations. varargin: A list of optional length of additional parameters that get handed off to fcn each time it is called. Note that if the program ends abnormally, it is possible to retrieve the current x, f, and H from the files g1.mat and H.mat that are written at each iteration and at each hessian update, respectively. (When the routine hits certain kinds of difficulty, it write g2.mat and g3.mat as well. If all were written at about the same time, any of them may be a decent starting point. One can also start from the one with best function value.)
0001 function [fh,xh,gh,H,itct,fcount,retcodeh] = csminwel(fcn,x0,H0,grad,crit,nit,varargin) 0002 %[fhat,xhat,ghat,Hhat,itct,fcount,retcodehat] = csminwel(fcn,x0,H0,grad,crit,nit,varargin) 0003 % fcn: string naming the objective function to be minimized 0004 % x0: initial value of the parameter vector 0005 % H0: initial value for the inverse Hessian. Must be positive definite. 0006 % grad: Either a string naming a function that calculates the gradient, or the null matrix. 0007 % If it's null, the program calculates a numerical gradient. In this case fcn must 0008 % be written so that it can take a matrix argument and produce a row vector of values. 0009 % crit: Convergence criterion. Iteration will cease when it proves impossible to improve the 0010 % function value by more than crit. 0011 % nit: Maximum number of iterations. 0012 % varargin: A list of optional length of additional parameters that get handed off to fcn each 0013 % time it is called. 0014 % Note that if the program ends abnormally, it is possible to retrieve the current x, 0015 % f, and H from the files g1.mat and H.mat that are written at each iteration and at each 0016 % hessian update, respectively. (When the routine hits certain kinds of difficulty, it 0017 % write g2.mat and g3.mat as well. If all were written at about the same time, any of them 0018 % may be a decent starting point. One can also start from the one with best function value.) 0019 global bayestopt_ 0020 [nx,no]=size(x0); 0021 nx=max(nx,no); 0022 Verbose=1; 0023 NumGrad= isempty(grad); 0024 done=0; 0025 itct=0; 0026 fcount=0; 0027 snit=100; 0028 %tailstr = ')'; 0029 %stailstr = []; 0030 % Lines below make the number of Pi's optional. This is inefficient, though, and precludes 0031 % use of the matlab compiler. Without them, we use feval and the number of Pi's must be 0032 % changed with the editor for each application. Places where this is required are marked 0033 % with ARGLIST comments 0034 %for i=nargin-6:-1:1 0035 % tailstr=[ ',P' num2str(i) tailstr]; 0036 % stailstr=[' P' num2str(i) stailstr]; 0037 %end 0038 f0 = feval(fcn,x0,varargin{:}); 0039 %ARGLIST 0040 %f0 = feval(fcn,x0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); 0041 % disp('first fcn in csminwel.m ----------------') % Jinill on 9/5/95 0042 if f0 > 1e50, disp('Bad initial parameter.'), return, end 0043 if NumGrad 0044 if length(grad)==0 0045 [g badg] = numgrad(fcn,x0, varargin{:}); 0046 %ARGLIST 0047 %[g badg] = numgrad(fcn,x0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); 0048 else 0049 badg=any(find(grad==0)); 0050 g=grad; 0051 end 0052 %numgrad(fcn,x0,P1,P2,P3,P4); 0053 else 0054 [g badg] = feval(grad,x0,varargin{:}); 0055 %ARGLIST 0056 %[g badg] = feval(grad,x0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13); 0057 end 0058 retcode3=101; 0059 x=x0; 0060 f=f0; 0061 H=H0; 0062 cliff=0; 0063 while ~done 0064 bayestopt_.penalty = f; 0065 g1=[]; g2=[]; g3=[]; 0066 %addition fj. 7/6/94 for control 0067 disp('-----------------') 0068 disp('-----------------') 0069 %disp('f and x at the beginning of new iteration') 0070 disp(sprintf('f at the beginning of new iteration, %20.10f',f)) 0071 %-----------Comment out this line if the x vector is long---------------- 0072 % disp([sprintf('x = ') sprintf('%15.8g %15.8g %15.8g %15.8g\n',x)]); 0073 %------------------------- 0074 itct=itct+1; 0075 [f1 x1 fc retcode1] = csminit(fcn,x,f,g,badg,H,varargin{:}); 0076 %ARGLIST 0077 %[f1 x1 fc retcode1] = csminit(fcn,x,f,g,badg,H,P1,P2,P3,P4,P5,P6,P7,... 0078 % P8,P9,P10,P11,P12,P13); 0079 % itct=itct+1; 0080 fcount = fcount+fc; 0081 % erased on 8/4/94 0082 % if (retcode == 1) | (abs(f1-f) < crit) 0083 % done=1; 0084 % end 0085 % if itct > nit 0086 % done = 1; 0087 % retcode = -retcode; 0088 % end 0089 if retcode1 ~= 1 0090 if retcode1==2 | retcode1==4 0091 wall1=1; badg1=1; 0092 else 0093 if NumGrad 0094 [g1 badg1] = numgrad(fcn, x1,varargin{:}); 0095 %ARGLIST 0096 %[g1 badg1] = numgrad(fcn, x1,P1,P2,P3,P4,P5,P6,P7,P8,P9,... 0097 % P10,P11,P12,P13); 0098 else 0099 [g1 badg1] = feval(grad,x1,varargin{:}); 0100 %ARGLIST 0101 %[g1 badg1] = feval(grad, x1,P1,P2,P3,P4,P5,P6,P7,P8,P9,... 0102 % P10,P11,P12,P13); 0103 end 0104 wall1=badg1; 0105 % g1 0106 save g1 g1 x1 f1 varargin; 0107 %ARGLIST 0108 %save g1 g1 x1 f1 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; 0109 end 0110 if wall1 % & (~done) by Jinill 0111 % Bad gradient or back and forth on step length. Possibly at 0112 % cliff edge. Try perturbing search direction. 0113 % 0114 %fcliff=fh;xcliff=xh; 0115 Hcliff=H+diag(diag(H).*rand(nx,1)); 0116 disp('Cliff. Perturbing search direction.') 0117 [f2 x2 fc retcode2] = csminit(fcn,x,f,g,badg,Hcliff,varargin{:}); 0118 %ARGLIST 0119 %[f2 x2 fc retcode2] = csminit(fcn,x,f,g,badg,Hcliff,P1,P2,P3,P4,... 0120 % P5,P6,P7,P8,P9,P10,P11,P12,P13); 0121 fcount = fcount+fc; % put by Jinill 0122 if f2 < f 0123 if retcode2==2 | retcode2==4 0124 wall2=1; badg2=1; 0125 else 0126 if NumGrad 0127 [g2 badg2] = numgrad(fcn, x2,varargin{:}); 0128 %ARGLIST 0129 %[g2 badg2] = numgrad(fcn, x2,P1,P2,P3,P4,P5,P6,P7,P8,... 0130 % P9,P10,P11,P12,P13); 0131 else 0132 [g2 badg2] = feval(grad,x2,varargin{:}); 0133 %ARGLIST 0134 %[g2 badg2] = feval(grad,x2,P1,P2,P3,P4,P5,P6,P7,P8,... 0135 % P9,P10,P11,P12,P13); 0136 end 0137 wall2=badg2; 0138 % g2 0139 badg2 0140 save g2 g2 x2 f2 varargin 0141 %ARGLIST 0142 %save g2 g2 x2 f2 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; 0143 end 0144 if wall2 0145 disp('Cliff again. Try traversing') 0146 if norm(x2-x1) < 1e-13 0147 f3=f; x3=x; badg3=1;retcode3=101; 0148 else 0149 gcliff=((f2-f1)/((norm(x2-x1))^2))*(x2-x1); 0150 if(size(x0,2)>1), gcliff=gcliff', end 0151 [f3 x3 fc retcode3] = csminit(fcn,x,f,gcliff,0,eye(nx),varargin{:}); 0152 %ARGLIST 0153 %[f3 x3 fc retcode3] = csminit(fcn,x,f,gcliff,0,eye(nx),P1,P2,P3,... 0154 % P4,P5,P6,P7,P8,... 0155 % P9,P10,P11,P12,P13); 0156 fcount = fcount+fc; % put by Jinill 0157 if retcode3==2 | retcode3==4 0158 wall3=1; badg3=1; 0159 else 0160 if NumGrad 0161 [g3 badg3] = numgrad(fcn, x3,varargin{:}); 0162 %ARGLIST 0163 %[g3 badg3] = numgrad(fcn, x3,P1,P2,P3,P4,P5,P6,P7,P8,... 0164 % P9,P10,P11,P12,P13); 0165 else 0166 [g3 badg3] = feval(grad,x3,varargin{:}); 0167 %ARGLIST 0168 %[g3 badg3] = feval(grad,x3,P1,P2,P3,P4,P5,P6,P7,P8,... 0169 % P9,P10,P11,P12,P13); 0170 end 0171 wall3=badg3; 0172 % g3 0173 badg3 0174 save g3 g3 x3 f3 varargin; 0175 %ARGLIST 0176 %save g3 g3 x3 f3 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13; 0177 end 0178 end 0179 else 0180 f3=f; x3=x; badg3=1; retcode3=101; 0181 end 0182 else 0183 f3=f; x3=x; badg3=1;retcode3=101; 0184 end 0185 else 0186 % normal iteration, no walls, or else we're finished here. 0187 f2=f; f3=f; badg2=1; badg3=1; retcode2=101; retcode3=101; 0188 end 0189 else 0190 f2=f;f3=f;f1=f;retcode2=retcode1;retcode3=retcode1; 0191 end 0192 %how to pick gh and xh 0193 if f3 < f - crit & badg3==0 0194 ih=3 0195 fh=f3;xh=x3;gh=g3;badgh=badg3;retcodeh=retcode3; 0196 elseif f2 < f - crit & badg2==0 0197 ih=2 0198 fh=f2;xh=x2;gh=g2;badgh=badg2;retcodeh=retcode2; 0199 elseif f1 < f - crit & badg1==0 0200 ih=1 0201 fh=f1;xh=x1;gh=g1;badgh=badg1;retcodeh=retcode1; 0202 else 0203 [fh,ih] = min([f1,f2,f3]); 0204 disp(sprintf('ih = %d',ih)) 0205 %eval(['xh=x' num2str(ih) ';']) 0206 switch ih 0207 case 1 0208 xh=x1; 0209 case 2 0210 xh=x2; 0211 case 3 0212 xh=x3; 0213 end %case 0214 %eval(['gh=g' num2str(ih) ';']) 0215 %eval(['retcodeh=retcode' num2str(ih) ';']) 0216 retcodei=[retcode1,retcode2,retcode3]; 0217 retcodeh=retcodei(ih); 0218 if exist('gh') 0219 nogh=isempty(gh); 0220 else 0221 nogh=1; 0222 end 0223 if nogh 0224 if NumGrad 0225 [gh badgh] = numgrad(fcn,xh,varargin{:}); 0226 else 0227 [gh badgh] = feval(grad, xh,varargin{:}); 0228 end 0229 end 0230 badgh=1; 0231 end 0232 %end of picking 0233 %ih 0234 %fh 0235 %xh 0236 %gh 0237 %badgh 0238 stuck = (abs(fh-f) < crit); 0239 if (~badg)&(~badgh)&(~stuck) 0240 H = bfgsi(H,gh-g,xh-x); 0241 end 0242 if Verbose 0243 disp('----') 0244 disp(sprintf('Improvement on iteration %d = %18.9f',itct,f-fh)) 0245 end 0246 % if Verbose 0247 if itct > nit 0248 disp('iteration count termination') 0249 done = 1; 0250 elseif stuck 0251 disp('improvement < crit termination') 0252 done = 1; 0253 end 0254 rc=retcodeh; 0255 if rc == 1 0256 disp('zero gradient') 0257 elseif rc == 6 0258 disp('smallest step still improving too slow, reversed gradient') 0259 elseif rc == 5 0260 disp('largest step still improving too fast') 0261 elseif (rc == 4) | (rc==2) 0262 disp('back and forth on step length never finished') 0263 elseif rc == 3 0264 disp('smallest step still improving too slow') 0265 elseif rc == 7 0266 disp('warning: possible inaccuracy in H matrix') 0267 end 0268 % end 0269 f=fh; 0270 x=xh; 0271 g=gh; 0272 badg=badgh; 0273 end 0274 % what about making an m-file of 10 lines including numgrad.m 0275 % since it appears three times in csminwel.m