home *** CD-ROM | disk | FTP | other *** search
- function [llf]=mmlegrad(p,pid,p2snam,perts,gg)
- % FUNCTION USED BY MMLE.M
- %USED BY MMLESTEP & MMLEMARQ TO GET GRADIENT, HESSIAN & OTHER DATA
- %Outputs :
- % - llf = Log Likelihood function. The following outputs are GLOBAL
- % - grad = Gradient of cost function wrt parameters in PID
- % - hes = Hessian (second gradient) of cost function wrt params in PID
- % - c0 = Measurement matrix %not called by anyone else.
- % - e0 = Diagonal of (Kalman gain * C)
- % - grade = Gradient of E0 wrt params in PID
- % - rowinq = Vector giving rows in F in which parameters occur, else [0]
- % - proc = Scalar flag >0 if process noise is being used.
- %
- % Inputs :
- % - p = Parameter vector (row)
- % - pid = Row vector of indices of params in P to be ID'd. eg [1 3 6]
- % - p2snam = Name of user defined function converting P to system.
- % e.g. P2SS . <Help ml_p2ss3> gives details.
- % - perts = Amount by which each parameter is perturbed to estimate
- % gradients by finite differences. Noncritical- try .001-.0001
- % - gg = Innovations covariance matrix. You get the first guess.
- % - uydata - GLOBAL VARIABLE -- see MMLELIKE.M
- %---------------------------------------------------------------------------
-
- global uydata
- global grad
- global grade
- global hes
- global e0
- global rowinq
- global yest
- global inovt
- global wersum
- global rr
-
- p2snamp=[p2snam,'(p)']; % ACCEPT ANY NAME FOR P2SS
- [a,phi,gam,c,d,q,x0,dt,rowinq]=eval(p2snamp);c0=c; % GET NOMINAL SYSTEM
- npid=length(pid);[nm,nx]=size(c);[ndp,xx]=size(uydata); % GET DIMENSIONS
- [nx,nu]=size(gam);num=nu+nm;nnorm=ndp;
- grade=ones(nx,npid); % DIMENSION MATRICES
- proc=sum(diag(q))>0; % USER SETS q TO ZERO FOR NO KALMAN GAIN
- %-------------------YEST,INOV,RR,LLF FOR NOMINAL P----------------------------
- if proc==0,
- k=zeros(nx,nm);
- else
- k=lqe(a,eye(nx),c,q*q'/dt/dt,gg)*dt; % EQN 30,MAINE & ILIFF, pp588-579
- end
- inovt=uydata(:,nu+1:num); % = TEMPORARY STORAGE FOR Y_MEAS
- yest=dlsim(phi*(eye(nx)-k*c),... % SIAM J. Appl. Math. Vol41, No3, Dec81
- [gam-phi*k*d,phi*k],c,[d,0*ones(nm)],uydata,x0);
-
- inovt=inovt-yest;
- rr=inovt'*inovt/nnorm; % INNOVATIONS AND SAMPLE COVARIANCE
- rtggit=chol(inv(gg))'; % OUTPUT VECTOR WEIGHTING FOR COST FUNCTION
- inovt=inovt*rtggit;yest=yest*rtggit; % WEIGHT YEST,INOVT
- %-------------------------------------------------------------------
-
- e0=diag(k*c); % FOR CONSTRAINING DIAG(E0) < EYE
- wersum=sum(sum(inovt.*inovt))/nnorm/nm;% WEIGHTED ERROR SUM
- llf=ndp/2*(wersum*nm-2*log(prod(diag(rtggit))));% FAST DET
- %----------------------------NOW GET GRAD, HES, OF COST WRT PARAMS
- psav=p;
- phipid=[];gampid=[];ctpid=[];dtpid=[];xpid=[];
-
- k=zeros(nx,nm);
- for jj=1:npid; % COMPUTE AND STACK KF MATRICES FOR ALL PERTURBATIONS
- p(pid(jj))=p(pid(jj))+perts(pid(jj));
- [a,phi,gam,c,d,q,x0,dt,rowinq]=eval(p2snamp); % GET PERTURBED SYSTEM
- if proc ~ 0; % KALMAN FILTER IF PROCESS NOISE
- % k=lqe(a,eye(nx),c,q*q'/dt/dt,gg)*dt; % CONT LQE FOR DISC! (SEE REF)
- [zzv,zzd]=eig([a' c'/gg*c;q*q'/dt/dt -a]);% THESE 5 LINES EQUIV TO LQE
- zzd=diag(zzd);[zzd,index]=sort(real(zzd));
- chi=zzv(1:nx,index(1:nx));
- lambda=zzv(nx+1:2*nx,index(1:nx));zzs=-real(lambda/chi);
- k=gg\c*zzs;k=k'*dt;
- end;
- phipid=[phipid;phi*(eye(nx)-k*c)];
- gampid=[gampid;[gam-phi*k*d,phi*k]];
- dtpid=[dtpid [d,0*ones(nm)]'*rtggit];
- grade(:,jj)=(diag(k*c)-e0)/perts(pid(jj)); % GRADIENT OF DIAG(E=K*C)
- %
- ctpid=[ctpid c'*rtggit]; % STACK C' IN ROWS
- xpid=[xpid;x0]; % STACK INITIAL CONDITIONS IN ROWS
- p=psav;
- fprintf(' ')
- end;fprintf('.')
-
- %PHI/GAM/CT/DT....PID MATRICES LOADED WITH ALL KALMAN FILTERS, XPID WITH IC's
-
- hes=zeros(npid);
- grad=zeros(npid,1);
- onepid=ones(1,npid);fstn=1;
- maxel=4094/2;% REDUCING THIS SLOWS ALGO, USES LESS MEMORY
- % YOU CAN MAKE IT GLOBAL BEFORE CALLING MMLE
-
- blocklen=fix(min([maxel/num,maxel/nm/npid]));% MAX BLOCK LENGTH (MEMORY!)
-
- fstn=1;
- while fstn<=ndp, % RUN KF AND SUM GRAD, HES IN TIME-BLOCKS (MEMORY!)
- lstn=min([ndp,fstn+blocklen-1]); % END CURRENT DATA BLOCK
- len=lstn-fstn+1;
- yes=yest(fstn:lstn,:)';yes=yes(:); % LONG COL OF NOMINAL KF OUTPUT
- gradz=yes*onepid;% NOMINAL ESTIMATE
- for i=1:npid % GET GRADIENT OF INNOVATIONS WRT EACH PARAMETER
- xrows=[1+(i-1)*nx:i*nx]; % ROWS/COLS STORING THIS KF'S MATRICES
- ycols=[1+(i-1)*nm:i*nm];
- a=phipid(xrows,:);b=gampid(xrows,:);
- x=ltitr(a,b,uydata(fstn:lstn,:),xpid(i,:)); % PROPAGATE KF STATES
- xpid(i,:)=x(len,:)*a'+uydata(lstn,:)*b'; % COMPUTE NEXT IC.
- x=x*ctpid(:,ycols)+uydata(fstn:lstn,:)*dtpid(:,ycols); % KF OUTPUTS
- x=x';
- gradz(:,i)=gradz(:,i)-x(:);% SUBTRACT COL VECTORS IN A LONG COL
- end,
- smes=(uydata(fstn:lstn,nu+1:num)*rtggit)';
- grad=grad+gradz'*(smes(:)-yes); % ACCUMULAATE GRAD. (INNOV IN PARENTHESES)
- hes=hes+gradz'*gradz; % ACCUMULATE HES
- fstn=fstn+blocklen; % START OF NEXT BLOCK
- fprintf(' ') % SHOW SOME LIFE
- end
- grad=grad./perts(pid)';ans=diag(exp(-log(perts(pid))));
- hes=ans*hes*ans; % ACCOUNT FOR SIZE OF PERT
- fprintf(':');disp(' ')
- %------------------------------------------------------------end mmlegrad.m
-