SPA Matlab Code(转载)

注释:代码转载自 https://sites.google.com/site/zaiyang0248/publication

 一、均匀线阵主程序

% test of SPA in the ULA case

clear all
close all
clc


K = 3;          % source number
M = 30;         % array length
N = 200;        % snapshot number
sigma = 1;      % noise variance

% true frequency and power
f = [.1; .11; .5];
p = [3; 3; 1];

A = exp(1i*2*pi*kron((0:M-1)',f'));
S = sqrt(diag(p))*exp(1i*2*pi*rand(K,N));
% S(K,:) = S(1,:); % sources 1 & K coherent
E = diag(sqrt(sigma/2)) * (randn(M,N)+1i*randn(M,N));

% observed snapshots
Y = A*S + E;

% parameter estimation using SPA
tic
mode = 1;  % noise variance mode, 1: equal; 2: different
[freq_est, pow_est] = SPA(Y, mode);
toc

% MSE
MSE = norm(f - sort(freq_est(1:K)))^2 / K;

% plot result
figure(100), semilogy(f, p, 'ko'), hold on;
semilogy(freq_est, pow_est, 'rx', 'MarkerSize', 5);
xlabel('Frequency');
ylabel('Power');
legend('Truth', 'Estimate');
title(strcat('Frequency MSE = ', num2str(MSE)));

二、稀疏线阵主程序

% test of SPA in the SLA case

clear all
close all
clc

K = 6;
Omega = [1; 2; 5; 7];
M = max(Omega);
L = length(Omega);
T = 200;

% true frequency and power
f = [.1; .18; .4; .55; .7; .85];
p = [2; 2; 2; 1; 1; 1];


% observed snapshots
X = exp(1i*2*pi*kron(Omega-1,f'));
S = diag(sqrt(p))*exp(1i*2*pi*rand(K,T));

sigma = .1;
E = sqrt(sigma/2) * (randn(L,T)+1i*randn(L,T));
Y = X*S + E;

% parameter estimation using SPA
tic
mode = 1;  % noise variance mode, 1: equal; 2: different
[freq_est, pow_est] = SPA(Y, mode, Omega);
toc

% MSE
MSE = norm(f - sort(freq_est(1:K)))^2 / K;

% plot result
figure(100), plot(f, p, 'ko'), hold on;
plot(freq_est, pow_est, 'rx', 'MarkerSize', 5);
xlabel('Frequency');
ylabel('Power');
% axis([0,1,0,3]);
legend('Truth', 'Estimate');
title(strcat('Frequency MSE = ', num2str(MSE)));

三、SPA函数

function [freq, pow] = SPA(Y, mode_noise, Omega)

% [freq, pow] = SPA(Y, mode_noise, Omega)
% 
% SPA implements the sparse and parametric approach (SPA) for linear array 
% signal processing.
% 
% Input
% Y: observation
% mode_noise: 1 if equal noise variances;
%             2 if different noise variances,
%             default value: 2
% Omega: index set of SLA, valid only in the SLA case, sorted ascendingly
% 
% Output:
% freq: frequency estimate
% pow: power estimate
% sigma: noise variance estimate
% 
% Reference: Z. Yang, L. Xie, and C. Zhang, "A discretization-free sparse 
%   and parametric approach for linear array signal processing", 
%   IEEE Trans. Signal Processing, 2014
% 
% Written by Zai Yang, April 2013

if nargin < 3 || max(Omega) == length(Omega)  % ULA
    Omega = [];
else
    if length(Omega) ~= size(Y,1)
        error('Dimension of Omega not match!');
    end
end
if nargin < 2
    mode_noise = 2;
end

[M, N] = size(Y);

if N > 1
    Rhat = Y * Y' / N;
end

cvx_quiet true
cvx_precision default

% solve the SDP (or estimate R)
if N >= M && cond(Rhat) < 1e8       % nonsingular
    [u, sig] = SPA_nonsing(Rhat, mode_noise, Omega);
    
elseif N == 1  % single snapshot
    [u, sig] = SPA_SMV(Y, mode_noise, Omega);
    
else           % multisnapshots and singular
    [u, sig] = SPA_singu(Rhat, mode_noise, Omega);
    
end

% postprocessing and parameter estimation
[freq, pow] = PostProc(u);

end



function [u, sig] = SPA_nonsing(Rhat, mode_noise, Omega)
% SPA when Rhat is nonsingular

if isempty(Omega)         % ULA
    M = size(Rhat, 1);
    
    Rhatinv = inv(Rhat);
    TconjR = zeros(M,1);
    TconjR(1) = trace(Rhatinv);
    for j = 2:M
        TconjR(j) = 2*sum(diag(Rhatinv,j-1));
    end
    
    Rhathalf = sqrtm(Rhat);
    
    switch mode_noise
            
        case 1,  % equal noise variances
            cvx_solver sdpt3
            cvx_begin sdp            
              variable x(M,M) hermitian,
              variable u(M) complex,
              
              [x Rhathalf; Rhathalf toeplitz(u)] >= 0,
              
              minimize trace(x) + real(TconjR'*u);
            cvx_end
            sig = 0;
            
        case 2,  % different noise variances
            cvx_solver sdpt3
            cvx_begin sdp
              variable x(M,M) hermitian,
              variable u(M) complex,
              variable sig(M), 
              
              sig >= 0,
              toeplitz(u) >= 0,
              [x Rhathalf; Rhathalf toeplitz(u)+diag(sig)] >= 0,
              
              minimize trace(x) + real(TconjR'*u) + real(diag(Rhatinv)')*sig;
            cvx_end
            
        otherwise,
            error('error!');
    end
    
    return
end


%% SLA

M = max(Omega);
Mbar = length(Omega);

Rhatinv = inv(Rhat);
Rhatinv_expand = zeros(M);
Rhatinv_expand(Omega, Omega) = Rhatinv;
TconjR = zeros(M,1);
TconjR(1) = trace(Rhatinv_expand);
for j = 2:M
    TconjR(j) = 2*sum(diag(Rhatinv_expand,j-1));
end

S = zeros(Mbar, M);
S(:, Omega) = eye(Mbar);

Rhathalf = sqrtm(Rhat);

switch mode_noise
        
    case 1,  % equal noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x(Mbar,Mbar) hermitian,
          variable u(M) complex,
          
          toeplitz(u) >= 0,
          [x Rhathalf; Rhathalf S*toeplitz(u)*S'] >= 0,
            
          minimize trace(x) + real(TconjR'*u);
        cvx_end
        
        sig = 0;
        
    case 2,  % different noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x(Mbar,Mbar) hermitian,
          variable u(M) complex,
          variable sig(Mbar), 
          
          sig >= 0,
          toeplitz(u) >= 0,
          [x Rhathalf; Rhathalf S*toeplitz(u)*S'+diag(sig)] >= 0,
            
          minimize trace(x) + real(TconjR'*u) + real(diag(Rhatinv)')*sig;
        cvx_end
        
    otherwise,
        error('error!');
end

end




function [u, sig] = SPA_SMV(Y, mode_noise, Omega)
% SPA in the single-snapshot case

if isempty(Omega)         % ULA
    M = length(Y);
    
    Y2n = norm(Y);
    
    switch mode_noise
            
        case 1,  % equal noise variances
            cvx_solver sdpt3
            cvx_begin sdp            
              variable x,
              variable u(M) complex,
              
              toeplitz(u) >= 0,
              [x Y2n*Y'; Y2n*Y toeplitz(u)] >= 0,
              
              minimize x + M*real(u(1));
            cvx_end
            
            sig = 0;
            
        case 2,  % different noise variances
            cvx_solver sdpt3
            cvx_begin sdp
              variable x,
              variable u(M) complex,
              variable sig(M), 
              
              sig >= 0,
              toeplitz(u) >= 0,
              [x Y2n*Y'; Y2n*Y toeplitz(u)+diag(sig)] >= 0,
              
              minimize x + M*real(u(1)) + sum(sig);
            cvx_end
            
        otherwise,
            error('error!');
    end
    
    return
end


%% SLA

M = max(Omega);
Mbar = length(Omega);

Y2n = norm(Y);

S = zeros(Mbar, M);
S(:, Omega) = eye(Mbar);

switch mode_noise
        
    case 1,  % equal noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x
          variable u(M) complex,
          
          toeplitz(u) >= 0,
          [x Y2n*Y'; Y2n*Y S*toeplitz(u)*S'] >= 0,
            
          minimize x + Mbar*real(u(1));
        cvx_end
        
        sig = 0;
        
    case 2,  % different noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x
          variable u(M) complex,
          variable sig(Mbar), 
          
          sig >= 0,
          toeplitz(u) >= 0,
          [x Y2n*Y'; Y2n*Y S*toeplitz(u)*S'+diag(sig)] >= 0,
            
          minimize x + Mbar*real(u(1)) + sum(sig);
        cvx_end
        
    otherwise,
        error('error!');
end

end







function [u, sig] = SPA_singu(Rhat, mode_noise, Omega)
% SPA when Rhat is singular

if isempty(Omega)         % ULA
    M = size(Rhat,1);
    
    switch mode_noise
            
        case 1,  % equal noise variances
            cvx_solver sdpt3
            cvx_begin sdp            
              variable x(M,M) hermitian,
              variable u(M) complex,
              
              toeplitz(u) >= 0,
              [x Rhat; Rhat toeplitz(u)] >= 0,
              
              minimize trace(x) + M*real(u(1));
            cvx_end
            
            sig = 0;
            
        case 2,  % different noise variances
            cvx_solver sdpt3
            cvx_begin sdp
              variable x(M,M) hermitian,
              variable u(M) complex,
              variable sig(M), 
              
              sig >= 0,
              toeplitz(u) >= 0,
              [x Rhat; Rhat toeplitz(u)+diag(sig)] >= 0,
              
              minimize trace(x) + M*real(u(1)) + sum(sig);
            cvx_end
            
        otherwise,
            error('error!');
    end
    
    return
end


%% SLA

M = max(Omega);
Mbar = length(Omega);

S = zeros(Mbar, M);
S(:, Omega) = eye(Mbar);

switch mode_noise
        
    case 1,  % equal noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x(Mbar,Mbar) hermitian,
          variable u(M) complex,
          
          toeplitz(u) >= 0,
          [x Rhat; Rhat S*toeplitz(u)*S'] >= 0,
            
          minimize trace(x) + Mbar*real(u(1));
        cvx_end
        
        sig = 0;
        
    case 2,  % different noise variances
        cvx_solver sdpt3
        cvx_begin sdp
          variable x(Mbar,Mbar) hermitian,
          variable u(M) complex,
          variable sig(Mbar), 
          
          sig >= 0,
          toeplitz(u) >= 0,
          [x Rhat; Rhat S*toeplitz(u)*S'+diag(sig)] >= 0,
            
          minimize trace(x) + Mbar*real(u(1)) + sum(sig);
        cvx_end
        
    otherwise,
        error('error!');
end

end




function [freq, amp] = PostProc(u)

% [freq, amp] = PostProc(u)
% PostProc implements the postprocessing procedure given the solution u.
% The result is sorted in the descending order of amp

prec = 1e-4; % can be tuned appropriately

eigval = sort(real(eig(toeplitz(u))));
if eigval(1) > 0
    sigma_in_u = eigval(1);
    u(1) = u(1) - sigma_in_u;
    eigval = eigval - sigma_in_u;
else
    sigma_in_u = 0;
end

K = sum(eigval > prec*eigval(end));

M = length(u);

% solve h
h = toeplitz([conj(u(2)); u(1:M-1)], conj(u(2:K+1))) \ (-u(1:M));

% solve the zeros of H(z) in the form of exp(-1i * 2 * pi * theta)
r = roots([1; h]);
% r = r ./ abs(r);

% solve the amper vector
mat = flipud(vander([r; zeros(M-K,1)]).');
amp = mat(:, 1:K) \ u;
[amp, idx] = sort(real(amp), 'descend');
Khat = sum(amp>0);
amp = amp(1:Khat);

% determine the frequency
freq = - phase(r(idx(1:Khat))) / (2*pi);
freq = mod(freq, 1);

end

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值