
% A simple CDMA simulation to demo comfac.m

% Reference:
% N. D. Sidiropoulos, G. B. Giannakis, and Rasmus Bro, 
% ``Blind PARAFAC Receivers for DS-CDMA Systems'', 
% IEEE Transactions on Signal Processing, 48(3):810-823, Mar. 2000

% demo by N. Sidiropoulos and R. Bro

clear all;

F=5;  % users
I=4;  % antennas
J=50; % symbol snapshots
K=4;  % spreading gain

A = randn(I,F)+j*randn(I,F); % array response
B = sign(randn(J,F)); % BPSK symbol matrix
for f=1:F, % for scaling ambiguity removal later:
 B(:,f) = B(:,f) / B(1,f);
end
C = randn(K,F); % randomly drawn symbol-periodic signatures

X = zeros(I,J,K);
for k=1:K,
 X(:,:,k) = A*diag(C(k,:))*B.';
end

% add noise if you wish:
% sig2 = 0.01;
% W = (sig2/2)*randn(size(X))+j*(sig2/2)*randn(size(X));
% X = X + W;

%[estA,estC,estB]=TALS(X,F); % plain-vanilla
[estA,estB,estC]=comfac(X,F); % faster and better

% remove permutation and scale ambiguity:

for f=1:F, % scaling ambiguity removal
 estB(:,f) = estB(:,f) / estB(1,f);
end

estB = sign(real(estB)); % hard decision detector

% now remove permutation ambiguity by greedy-LS column matching:

% Calculate permutation that best matches the signal streams
% This is done for performance evaluation purposes only.
% Here we do it in a greedy (suboptimal) way, which is, nevertheless,
% robust & computationally efficient for any number of users.
% define a distance matrix DISTMAT whose element DISTMAT(i,j) is the
% distance between i-th transmitted signal and j-th received signal

DISTMAT=ones(F,F);
for sd=1:F
 for rs=1:F
  DISTMAT(sd,rs)=norm(B(:,sd)-estB(:,rs),'fro');
 end
end
maxD=max(max(DISTMAT))+1;

fS=ones(size(B));
for k=1:F
 row_ps=0;col_ps=0;
 minD=min(min(DISTMAT));
 % the following can be more efficiently done, but what the heck:
 for row=1:F
  for col=1:F
   if (minD==DISTMAT(row,col)) row_ps=row; col_ps=col; end
  end
 end
 fS(:,row_ps)=estB(:,col_ps);
 DISTMAT(row_ps,:)=maxD*ones(size(DISTMAT(row_ps,:)));
 DISTMAT(:,col_ps)=maxD*ones(size(DISTMAT(:,col_ps)));
end

estB = fS;

B
estB

NumBitErrors  = norm(B ~= estB,'fro')^2

BER = NumBitErrors/(J*F)

figure(1);
clf;
for f=1:F,
 subplot(F,1,f);
 bar(B(:,f));
end

figure(2);
clf;
for f=1:F,
 subplot(F,1,f);
 bar(estB(:,f),'r');
end

disp('Blue - true user signals; Red - blind PARAFAC estimates');
