📄 simplex.m
字号:
function [pout,deltapout,r2,ss,f,func_evals,kvg,ChiSq,v,fv]=simplex(x,ys,pin,func,wt,dp,niter,stol,last)% simplex : Simplex routine (see fmins matlab function)% FMINS uses a Nelder-Mead type simplex search method.% Syntax: [p,deltap,r2,rv,f,iter,kvg,ChiSq,v,fv]=% simplex(x,y,Pin,Func,{wt,dp,niter,stol,mode='normal'})%% INPUT:% x,y (vect) : data to be fitted.% Pin (vect) : initial values for parameter search.% Func (string) : function name (between quotes), of the form 'f(x,p)'.%% OUTPUT:% p (vect) : final parameters.% r2 (scalar) : correlation coefficient for fit.% deltap (v) : sigma on parameters% rv (scalar) : residual variance.% f (vect) : function values at the end of fitting process.% ChiSq : Chi Squarred%% ---------------% OPTIONS IN:% wt (s or v) : statistical weights for error calculation (1/sqrt(y) is defualt).% dp (s or v) : variation window for parameters, 0 for fixed param (0.1 is default, 0 to fix param)% niter (integ) : maximal number of iterations (20 is deualt).% stol (scal) : tolerency on square error sum fractional improvement (0.1 is default).% mode : 'silent', 'min', 'normal' or 'verbose' (do plot)%% OPTIONS OUT:% iter (integer): number of iterations processed.% kvg (boolean) : convergence flag (1 if ok).% v (matrix) : set of parameters used in fit% fv (vector) : set of RV for each set in 'v'% EF 09.97 from numerical recipies in C and FMINS matlab function% argument processing -----------------------------------------------if nargin < 9, last = []; endif nargin < 8, stol = []; endif nargin < 7, niter = []; endif nargin < 6, dp = []; endif nargin < 5, wt = []; endif isempty(last) last = 'normal';endif strcmp(last,'silent') tmp = 0;elseif strcmp(last,'min') tmp = 1;elseif strcmp(last,'verbose') tmp = 3;else tmp = 2;endif tmp>0 fprintf(1,'\nSimplex Multivariable Fit\n');endif isempty(dp) dp=.1; if (tmp>1) disp('dp = 0.1 (10 %) '); endendif isempty(wt) wt=1./sqrt(abs(ys+(ys == 0))); if (tmp>1) disp('using standard normalisation (1/sqrt(y))') endend % data weightsif isempty(niter) niter=20; if (tmp>1) fprintf(1,'Iterations : %i\n',niter); endend % max nb of itersif isempty(stol) stol=.1; if (tmp>1) fprintf(1,' Tolerancy : %g\n',stol); endend % tolerancyif length(wt) == 1 wt = wt * ones(length(ys),1);endnzerow = find(wt);zerow = find(wt == 0);if ~isempty(zerow) if tmp>1 disp('Get selected points'); end x = x(nzerow); ys = ys(nzerow); wt = wt(nzerow);end%change all vectors to columnsx=x(:);y=ys(:);wt=wt(:);pin=pin(:);dp=dp(:);% check data vectors- same length?m=length(y); n=length(pin); p=pin;[m1,m2]=size(x);if (m1~=m) error('input(x)/output(y) data must have same number of rows ');endif (m > 10000) warning('HUH ! That makes a lot of points ! I may crash during fit...');endif (m <= n) disp('Warning : need to extend data...'); newm = ceil(n/m+1)*m; newx = linspace(x(1), x(length(x)), newm); newx = newx(:); y = interpsp(x,y,newx); wt = interpsp(x,wt,newx); x=newx; m = newm;endif (length(dp) == 1) dp=dp*ones(n,1);end% interface/call to fmins --------------------------------------------------funfcn=func;xsav=x;ysav=y;x=pin;fixed=find(dp == 0);notfixed = (dp ~= 0);tol=dp;tol2=stol;% f=feval(funfcn,xsav,x); r=wt.*(ysav-f); f=r'*r;% FMINS --------------------------------------------------n = prod(size(x));% Set up a simplex near the initial guess.xin = vect2column(x); % Force xin to be a column vectorv = xin; % Place input guess in the simplex! (credit L.Pfeffer at Stanford)x(:) = v;f=vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fv=r'*r;pbest=x;ssbest=fv;fbest=f;niter=niter*length(find(dp));tic% Following improvement suggested by L.Pfeffer at Stanfordusual_delta = tol; % percent deltas for non-zero termszero_term_delta = tol/50; % Even smaller delta for zero elements of xfor j = find(dp') y = xin; if y(j) ~= 0 y(j) = (1 + usual_delta(j))*y(j); else y(j) = zero_term_delta; end% y(fixed)=pin(fixed); v = [v y]; x(:) = y; f = feval(funfcn,xsav,x); r=wt.*(ysav-f); f=r'*r; fv = [fv f]; y = xin; if y(j) ~= 0 y(j) = (1 - usual_delta(j))*y(j); else y(j) = -zero_term_delta; end% y(fixed)=pin(fixed); v = [v y]; x(:) = y; f = feval(funfcn,xsav,x); r=wt.*(ysav-f); f=r'*r; fv = [fv f];end[fv,j] = sort(fv);v = v(:,j);[np1,n] = size(v);n = n-1;func_evals = n+1;if tmp > 0disp('')disp(sprintf('*Beginning fit (max %d iterations)',niter));if tmp > 1disp('--------------------------------------')disp('Iteration Time(s) Residual Variance');fprintf(1,' %3d %6.2f %8.3f %s\n', func_evals, toc, fv(1)/length(ysav),'initial (best)');endendalpha = 1; beta = 1/2; gamma = 2;onesn = ones(1,n);ot = 2:n+1;on = 1:n;% Iterate until the diameter of the simplex is less than tol.while func_evals < niter if max(abs(fv(1)-fv(ot))) <= tol2 break end % One step of the Nelder-Mead simplex algorithm vbar = (sum(v(:,on)')/n)'; vr = (1 + alpha)*vbar - alpha*v(:,n+1); vr(fixed)=pin(fixed); x(:) = vr; f = vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fr=r'*r; func_evals = func_evals + 1; vk = vr; fk = fr; how = 'reflect '; if fr < fv(n) if fr < fv(1) ve = gamma*vr + (1-gamma)*vbar; ve(fixed)=pin(fixed); x(:) = ve; f=vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fe=r'*r; func_evals = func_evals + 1; if fe < fv(1) vk = ve; fk = fe; how = 'expand '; end end else vt = v(:,n+1); ft = fv(n+1); if fr < ft vt = vr; ft = fr; end vc = beta*vt + (1-beta)*vbar; vc(fixed)=pin(fixed); x(:) = vc; f=vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fc=r'*r; func_evals = func_evals + 1; if fc < fv(n) vk = vc; fk = fc; how = 'contract'; else for j = 2:n v(:,j) = (v(:,1) + v(:,j))/2; x(:) = v(:,j); f=vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fv(j)=r'*r; end func_evals = func_evals + n-1; vk = (v(:,1) + v(:,n+1))/2; vk(fixed)=pin(fixed); x(:) = vk; f=vect2column(feval(funfcn,xsav,x)); r=wt.*(ysav-f); fk=r'*r; func_evals = func_evals + 1; how = 'shrink '; end end v(:,n+1) = vk; fv(n+1) = fk; [fv,j] = sort(fv); v = v(:,j); iter=func_evals; ss=sum(((f-ysav).*wt).^2/length(ysav)); if (tmp > 1) fprintf(1,' %3d %6.2f %8.3f %s', iter, toc, ss,how); end if (ss <= ssbest) pbest=x; ssbest=ss; fbest=f; if (tmp>1) fprintf(1,' (best)'); end end if (tmp>1) fprintf(1,'\n'); endendx(:) = v(:,1);if func_evals>=niterendif func_evals==niter if tmp>0 disp(' Getting best fit... ') end kvg=0;else kvg=1;end% --------------------------------------------------% set return values%p=pbest;f=fbest;y=ysav;x=xsav;r=corrcoef(y.*wt,f.*wt);r2=r.*r';ss=sum(((f-ysav).*wt).^2/length(ysav));% now evaluates 'v' params dispersion near final solution : statistic evaluation in simplex% v is nparams columnssig2=std(v');sig = sig2.*notfixed';fv = fv/length(y); % get residual variancesif tmp>0 fprintf(1,'Best RV : %.3f - Worse RV : %.3f \n', min(fv),max(fv));end%-------- Work out Chi squared ------------------------v=length(y)-length(find(dp)); % # of degrees of freedom (#sel points - #free pars)ChiSq = sum( ((y-f).*wt).^2 )/v;pout = vect2column(p);deltapout = vect2column(sig);if (tmp>0) disp( '* Least Square Estimates of Parameters') disp(' value sigma(+/-)') disp([ pout deltapout ]) disp( '* Correlation Coefficient for fit R^2') disp(r2) disp( '* Residual Variance') disp(ss); disp('* Chi squared') disp(ChiSq)endif (tmp>2) fprintf(1,'Fit results sent to graph...\n'); title('Fit result'); xlabel('X'); ylabel('Y'); plot(x(:,1),y,x(:,1),f); % plot commandendp=p';if (size(ys,1)==1) f = f';end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -