function r=arma_ac(A,C,N);
% r=arma_ac(A,C,N);
% Calcola i campioni r(0), r(1), ..., r(N) della funzione di
% auto-covarianza del processo ARMA   A(z) y(t) = C(z) e(t)
% con A = [1 a1 .... an] e C=[1 c1 .... cm]
n=max(length(A),length(C));
A=[A zeros(1,n-length(A))];
C=[C zeros(1,n-length(C))];
n=n-1;
Ma=toeplitz(A,[1 zeros(1,n)])+[zeros(n,1) hankel(A(2:n+1)); zeros(1,n+1)];
Hc=hankel(C);
Ta=toeplitz(A,[1 zeros(1,n)]);
r=inv(Ma)*Hc*inv(Ta)*C';
A2=A(2:length(A));
for i=n+1:N
    r(i+1)=-A2*r(i:-1:i-n+1);
end;


function [r,rm]=arma_cra(A,C,N);
% Analisi di correlazione di processi ARMA
% [r,rm]=arma_cra(A,C,N);
% r=[1 r(1) ... r(N)] e' la auto-correlazione teorica calcolata risolvendo le equazioni di % Yule-Walker
% rm                  e' la auto-correlazione campionaria (correlogramma)
r=arma_ac(A,C,N);
r=[r(N+1:-1:2); r];
figure
plot([-N:N],r);
title('Funzione di auto-correlazione');
xlabel('k');
ylabel('r(k)');
M=10000;
e=randn(M,1);
y=filter(C,A,e);
rm=xcov(y,N,'unbiased');
pause;
hold on;
plot([-N:N],rm,'r');
legend('correlazione teorica','correlazione sperimentale');


function arma_time(A,C,N);
% r=arma_ac(A,C,N);
% Grafica la funzione di
% auto-covarianza del processo ARMA   A(z) y(t) = C(z) e(t)
% con A = [1 a1 .... an] e C=[1 c1 .... cm]
r=arma_ac(A,C,N);
r=[r(N+1:-1:2); r];
figure;
plot([-N:N],r);

function s=arma_psd(A,C,N);
% arma_psd(A,C,N);
% Calcola la densità spettrale, normalizzata dalla varianza del rumore bianco, 
% del processo ARMA A(z) y(t) = C(z) e(t)
% con A=[1 a1 .... an] e C=[1 c1 .... cm]
% in corrispondenza dei valori di pulsazione k pi/N per k=1,2,....,N
n=max(length(A),length(C));
A=[A zeros(1,n-length(A))];
C=[C zeros(1,n-length(C))];
n=n-1;
M=[1:N]'*[0:n];
w=[pi/N:pi/N:pi];
w0=exp(i*pi/N);
M=w0.^M;
s1=M*C';
s2=M*A';
s=abs(s1./s2).^2;


function [s,sm]=arma_spa(A,C,N);
% Analisi spettrale di processi ARMA
% [s,sm]=arma_spa(A,C,N);
% s:  densità spettrale teorica
% sm: densità spettrale campionaria (periodogramma)
n=max(length(A),length(C));
A=[A zeros(1,n-length(A))];
C=[C zeros(1,n-length(C))];
n=n-1;
s=arma_psd(A,C,N);
w=[pi/N:pi/N:pi];
figure;
title('Densita spettrale di potenza');
xlabel('Pulsazione');
ylabel('PSD');
plot(w,s);
M=10000;
e=randn(M,1);
y=filter(C,A,e);
% Uso del comando spa (Spectral Analysis)
mod=spa(y,50,w);
sm=mod.SpectrumData(:);
w=mod.freq(:);
% Uso del comando etfe (Empirical Transfer Function Estimate)
%mod=etfe(y,[],N);
%sm=mod.SpectrumData(:);
%w=mod.freq(:);
% Uso del comando pwelch
%[sm,w]=pwelch(y,[],[],2*N);
%sm=sm(2:N+1);
%w=w(2:N+1);
% Uso del comando periodogram
%[sm,w]=periodogram(y,[],2*N);
pause
hold on;
plot(w,sm,'r');
legend('teorica','sperimentale');


function s=arma_freq(A,C,N);
% arma_psd(A,C,N);
% Graficaar la densita' spettrale, normalizzata dalla varianza del rumore bianco, 
% del processo ARMA A(z) y(t) = C(z) e(t)
% con A=[1 a1 .... an] e C=[1 c1 .... cm]
% in corrispondenza dei valori di pulsazione k pi/N per k=1,2,....,N
s=arma_psd(A,C,N);
w=[pi/N:pi/N:pi];
figure;
plot(w,s);


function [alpha,beta,eps]=spectral_approx(phi,omega,n)
% Approssima la densit? spettrale phi valutata nelle pulsazioni del 
% vettore omega con una funzione razionale di ordine n
% Restituisce in uscita: il vettore alpha = [ 1, ..., alpha_n] dei
% coefficienti del denominatore; il vettore beta = [ beta_0, ..., beta_n]
% dei coefficienti del numeratore; l'errore massimo eps
% dell'approssimazione razionale
N=length(phi);
q=2*cos(kron(1:n,omega));
Phi=[-diag(phi)*q,ones(N,1),q];
theta=(Phi'*Phi)\(Phi'*phi);
alpha=[1;theta(1:n)];
np=length(theta);
beta=theta(n+1:np);
eps=max(abs(phi-Phi*theta));


function [r,q]=spectral_fact(p);
    % Risolve la fattorizzazione spettrale polinomiale p(z)=rq(z)q(z^-1)
    % di un polinomio simmetrico p(z) determinando l'unico fattore
    % spettrale monico q(z) = 1 + ... + qn z^(-n) con radici in |z|<=1
    n=length(p)-1;
    rho=[p(n+1:-1:2) p];
    z=roots(rho);
    z=complex(z);
    [m,i]=sort(abs(z));
    z=z(i);
    z=z(1:n);
    q=poly(z);
    r=(-1)^n*rho(1)/prod(z);

function state_stat;
% propagazione di media e varianza delo stato (ellisse di confidenza)
% di un sistema LTI
N=30;
r=0.9;
w0=pi/4;
A=[2*r*cos(w0) -r^2; 1 0];
%A=[1 1; 0 1];
B=[1;0];
D=[0;1];
Q=1;
u=3*ones(N,1);
m=[0;0];
P=[150 0; 0 150];
x0=[17;-20];
x=x0;
w=randn(1,N);
plot(x0(1),x0(2),'s');
hold on;
grid
draw_ellipse(m,P);
pause
for t=1:N;
    x=A*x+B*u(t)+D*w(t);
    m=A*m+B*u(t);
    P=A*P*A'+D*Q*D';
    plot(x(1),x(2),'s');
    draw_ellipse(m,P);
    pause
end;



function draw_ellipse(m,P);
% Disegna l'ellisse di confidenza al 95%
% di equazione (x-m)'P^{-1}(x-m)=c
% con P=P'>0 (2 x 2), m (2 x 1), c=5.99 (vedi tabella chi-quadro con 2
% gradi di liberta')
% draw_ellipse(m,P,c)
c=5.99; % p=Prob(x appartiene all'ellisse)=0.95
T=chol(P)';
A=T*[0 2*pi; -2*pi 0]*inv(T);
S=ss(A,zeros(2,1),eye(2),zeros(2,1));
t=[0:0.01:1];
plot(m(1),m(2),'ro');
hold on;
[v,d]=eig(P);
x0=sqrt(d(1)*c)*v(:,1);
x=initial(S,x0,t);
x(:,1)=x(:,1)+m(1);
x(:,2)=x(:,2)+m(2);
plot(x(:,1),x(:,2),'r');