├── .gitattributes ├── GaussianMomentsComputation.m ├── demoone_bitDOA.m └── onebitdoa_uninfor_iter.m /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /GaussianMomentsComputation.m: -------------------------------------------------------------------------------- 1 | function [mout, vout] = GaussianMomentsComputation(y, tauin, phatin, vpin, vnin) 2 | % GaussianMomentsComputation returns posterior mean and variance for E(z|y) 3 | % and Var(z|y), where y=sign(z+tau+w) 4 | % Input: 5 | % - y: sign measurements 6 | % - phatin: prior mean of z 7 | % - vpin: prior variance of z 8 | % - vnin: additive noise of w 9 | % - tauin: thresholds 10 | % Output: 11 | % - mout: E(Z | Y = y) 12 | % - vout: Var(Z | Y = y) 13 | 14 | % E(Z | Y = y) 15 | alpha = (phatin+tauin) ./ sqrt(vpin+vnin); 16 | 17 | 18 | C = y.*alpha; 19 | CDF = normcdf(C,0,1); 20 | ll = log(CDF); 21 | %Find bad values that cause log cdf to go to infinity 22 | I = find(C < -30); 23 | %This expression is equivalent to log(normpdf(C)) for 24 | %all negative arguments greater than -38 and is 25 | %numerically robust for all values smaller. DO NOT USE 26 | %FOR LARGE positive x. 27 | ll(I) = -log(2)-0.5*C(I).^2+log(erfcx(-C(I)/sqrt(2))); 28 | temp = exp(log(normpdf(alpha))-ll)./sqrt(vpin+vnin); 29 | % temp = normpdf(0,phatin+tauin,sqrt(vpin+vnin))./ normcdf(y.*alpha); 30 | % temp = normpdf(alpha)./ (0.5*erfc(-y.*alpha/sqrt(2)))./sqrt(vpin+vnin); 31 | mout = phatin+sign(y).*vpin.*temp; 32 | % Var(Z | Y = y) 33 | % temp1 = (phatin./vpin-tauin./vnin)./(1./vpin+1./vnin)-phatin; 34 | temp1 = (phatin.*vnin-tauin.*vpin)./(vpin+vnin)-phatin; 35 | if(isnan(temp1)) 36 | display('warning, temp1 is nan'); 37 | end 38 | vout = vpin+sign(y).*temp.*temp1.*vpin-(vpin.*temp).^2; 39 | 40 | % max(vout) 41 | 42 | % % E(Z | Y = y) 43 | % alpha = (phatin+tauin) ./ sqrt(vpin+vnin); 44 | % temp = normpdf(0,phatin+tauin,sqrt(vpin+vnin))./ normcdf(y.*alpha); 45 | % mout = phatin+sign(y).*vpin.*temp; 46 | % % Var(Z | Y = y) 47 | % temp1 = (phatin./vpin-tauin./vnin)./(1./vpin+1./vnin)-phatin; 48 | % vout = vpin+sign(y).*temp.*temp1.*vpin-(vpin.*temp).^2; 49 | end 50 | 51 | -------------------------------------------------------------------------------- /demoone_bitDOA.m: -------------------------------------------------------------------------------- 1 | % Onebit DOA via the generalized SBL algorithm 2 | % This code is written by Jiang Zhu and Xiangming Meng. If you have any 3 | % problems, please feel free to contact Jiang Zhu via jiangzhu16@zju.edu.cn 4 | % Paper: X. Meng and J. Zhu, A generalized sparse Bayesian learning 5 | % algorithm for one-bit DOA estimation, IEEE Communications Letters, 6 | % vol. 22, no. 7, pp. 1414-1417, 2018. 7 | 8 | clc; clear; close all; 9 | rng(6) % 2,3,4,5,6 work 10 | N = 361; % grid size 11 | maxit_outer = 400; 12 | supp=[181-6 181+4 181+75*2]; 13 | K = length(supp); 14 | x_dB = [12;22;20]; % amplitudes 15 | % Bearing grid 16 | theta = (-90:180/(N-1):90); 17 | theta_r = theta*pi/180; 18 | u = sin(theta_r); 19 | d = 1/2; % intersensor spacing 20 | SNRdB = 40; % [40] 21 | M = 256; 22 | L = 1; 23 | c_sign = @(cpl_num)sign(real(cpl_num))+1j*sign(imag(cpl_num)); 24 | wvar0 = 1; 25 | 26 | q = 0:1:(M-1); % sensor numbering 27 | xq = (q-(M-1)/2)*d; % sensor locations 28 | A = exp(-1i*2*pi*xq'*u)/sqrt(N); % M*N 29 | x_amp = 10.^(x_dB/20); 30 | x_amp = x_amp*ones(1,L); 31 | X = zeros(N,L); 32 | X(supp,:) = x_amp.*exp(1j*2*pi*rand(K,L)); 33 | if(L>1) 34 | wvar = ((norm(A*X,'fro'))^2/M/L)*10^(-SNRdB/10); 35 | else 36 | wvar = (norm(A*X))^2/M*10^(-SNRdB/10); 37 | end 38 | % noise generation 39 | w = sqrt(wvar/2)*randn(M,L)+1i*sqrt(wvar/2)*randn(M,L); 40 | Y = c_sign(A*X+w); 41 | % noise variance match 42 | [theta_uninfor, NMSE_SBL,X_debiased] = onebitdoa_uninfor_iter( N, L, M, K, X, Y, wvar, maxit_outer ); 43 | % noise variance mismatch 44 | [theta_uninfor_mismatch, NMSE_SBL_mismatch,X_debiased1] = onebitdoa_uninfor_iter( N, L, M, K, X, Y, wvar, maxit_outer ); 45 | 46 | theta_uninfor 47 | theta_uninfor_mismatch 48 | figure(1) 49 | semilogx(1:maxit_outer,NMSE_SBL,'-b+',... 50 | 1:maxit_outer,NMSE_SBL_mismatch,'-r<') 51 | xlim([1 maxit_outer]) 52 | legend('matched','mismatched') 53 | xlabel('iterations') 54 | ylabel('debiased NMSE (dB)') 55 | 56 | figure(2) 57 | stem(abs(X_debiased),'ro') 58 | hold on 59 | stem(abs(X_debiased1),'b*') 60 | legend('matched','mismatched') 61 | 62 | 63 | -------------------------------------------------------------------------------- /onebitdoa_uninfor_iter.m: -------------------------------------------------------------------------------- 1 | function [ thetadegree_est, NMSE_SBL,X_debiased ] = onebitdoa_uninfor_iter( N, L, M, K, X, Y, wvar, maxit_outer ) 2 | % One bit DOA estimator utilizing SBL 3 | % Written by Jiang Zhu and Xiangming Meng 4 | % 2017, Nov. 26 5 | 6 | % Input: A: Steering matrix 7 | % X: True Complex coefficients 8 | % N: Grid size 9 | % L: Number of snapshots 10 | % M: Number of attennas 11 | % K: Number of sources. For DOA estimation, it is not needed. 12 | ct = 0; 13 | % ULA-horizontal 14 | d = 1/2; % intersensor spacing 15 | q = 0:1:(M-1); % sensor numbering 16 | xq = (q-(M-1)/2)*d; % sensor locations 17 | 18 | % Bearing grid 19 | theta = (-90:180/(N-1):90); 20 | thetadeg = theta; 21 | theta_r = theta*pi/180; 22 | u = sin(theta_r); 23 | % Represenation matrix (steering matrix) 24 | A = exp(-1i*2*pi*xq'*u)/sqrt(N); % M*N 25 | 26 | NMSE_SBL = zeros(maxit_outer,1); 27 | % input initialization 28 | z_A_ext = zeros(M,L); 29 | Lar_num = 1e20; 30 | v_A_ext = Lar_num*ones(M,L); 31 | X_est = zeros(size(X)); 32 | X_est_old = zeros(size(X)); 33 | var_min = 1e-20; 34 | var_max = 1e20; 35 | 36 | % parameter initialization 37 | alpha = 1e-1*ones(N,1); 38 | alpha_all = zeros(N,L); 39 | a = 1+eps; 40 | b = 0+eps; 41 | 42 | for i = 1:maxit_outer 43 | % waitbar(i/maxit_outer) 44 | v_A_ext = var_max*(v_A_ext<=0)+v_A_ext.*(v_A_ext>0); 45 | v_A_ext = min(v_A_ext,var_max); 46 | v_A_ext = max(v_A_ext,var_min); 47 | % set up the parallel computing toolbox 48 | for snap = 1:L 49 | v_A_ext_snap = v_A_ext(:,snap); 50 | z_A_ext_snap = z_A_ext(:,snap); 51 | y = Y(:,snap); 52 | % transforming to real observations 53 | z_A_ext_real = [real(z_A_ext_snap);imag(z_A_ext_snap)]; 54 | y_real = [real(y);imag(y)]; 55 | v_A_ext_snap_real = [v_A_ext_snap;v_A_ext_snap]/2; 56 | [z_B_post_real, v_B_post_real] = GaussianMomentsComputation(y_real, 0, z_A_ext_real, v_A_ext_snap_real, wvar/2); 57 | v_B_post_snap = v_B_post_real(1:M)+v_B_post_real(M+1:end); 58 | z_B_post_snap = z_B_post_real(1:M)+1j*z_B_post_real(M+1:end); 59 | v_B_ext_snap = v_B_post_snap.*v_A_ext_snap./(v_A_ext_snap-v_B_post_snap+eps); 60 | z_B_ext_snap = v_B_ext_snap.*(z_B_post_snap./v_B_post_snap-z_A_ext_snap./v_A_ext_snap); 61 | % sum(isnan(z_B_ext_snap)) 62 | v_B_ext_snap = var_max*(v_B_ext_snap<=0)+v_B_ext_snap.*(v_B_ext_snap>0); 63 | v_B_ext_snap = min(v_B_ext_snap,var_max); 64 | v_B_ext_snap = max(v_B_ext_snap,var_min); 65 | 66 | beta = 1./v_B_ext_snap; 67 | y_tilde = z_B_ext_snap; 68 | Sigma = inv((A'*diag(beta)*A)+diag(alpha)); % Sigma: posterior variance 69 | Sigma = (Sigma+Sigma')/2; 70 | mu = Sigma*A'*diag(beta)*y_tilde; 71 | alpha_update = a./(mu.*conj(mu)+diag(Sigma)+b); 72 | X_est(:,snap) = mu; 73 | alpha_all(:,snap) = alpha_update; 74 | z_A_post_snap = A*mu; 75 | v_A_post_snap = diag(A*Sigma*A'); 76 | v_A_post_snap = (v_A_post_snap+conj(v_A_post_snap))/2; 77 | 78 | v_A_ext_snap = v_A_post_snap.*v_B_ext_snap./(v_B_ext_snap-v_A_post_snap+eps); 79 | z_A_ext_snap = v_A_ext_snap.*(z_A_post_snap./v_A_post_snap-y_tilde./v_B_ext_snap); 80 | v_A_ext_snap = var_max*(v_A_ext_snap<=0)+v_A_ext_snap.*(v_A_ext_snap>0); 81 | 82 | v_A_ext_snap = min(v_A_ext_snap,var_max); 83 | v_A_ext_snap = max(v_A_ext_snap,var_min); 84 | 85 | v_A_ext(:,snap) = v_A_ext_snap; 86 | z_A_ext(:,snap) = z_A_ext_snap; 87 | end 88 | 89 | alpha = mean(alpha_all,2); 90 | c = diag(X_est'*X)./diag(X_est'*X_est); 91 | NMSE_SBL(i) = 20*log10(norm(X_est*diag(c)-X,'fro')/norm(X,'fro')); 92 | if(norm(X_est_old-X_est,'fro')/norm(X_est)<1e-3) 93 | ct = ct+1; 94 | if(ct==3) 95 | break; 96 | end 97 | end 98 | X_est_old = X_est; 99 | end 100 | X_debiased = X_est*diag(c); 101 | [~,index_X] = sort(abs(X_est*X_est'),'descend'); 102 | thetadegree_est = thetadeg(index_X(1:K)); 103 | end 104 | 105 | --------------------------------------------------------------------------------