⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sea_det.m

📁 sphere decoding for MIMO communication system
💻 M
字号:
function [xHat,wHat,nv,nf,nl] = SEA_det(m,xMax,y,H,cplx)%% [xHat,wHat,nv,nf,nl] = SEA_det(m,xMax,y,H,cplx)%% Given inputs -% % m    : the problem dimension, i.e., the number of symbols to decode,% xMax : a parameter specifying the admissible solution space, e.g.,%        each element of xHat can take values in {-xMax+1,..,-1,0,1,..,xMax},% y    : a real or complex target signal (column) vector,% H    : a real or complex linear transform matrix, e.g., a MIMO channel, and% cplx : flag specifying if xHat should be (0) real- or (1) complex-valued.% % SEA_det returns -% % xHat : a possibly suboptimal solution to   argmin    |y - H*x|^2,%                                          x \in Z_*^m %        where Z_*^m is the set of integers such that -xMax < Z_* <= xMax,% wHat : the squared distance |y - H*xHat|^2, i.e., the solution node weight,% nv   : the number of nodes expanded by the detector,% nf   : the (approximate) number of floating points operations performed%        (excluding pre-processing, e.g., QR factorization),% nl   : the number of leaf nodes visited by the detector.%   % The real-valued version of this depth-first stack-based sequential decoding% algorithm uses a decoding tree of m+1 levels where each node has 2*xMax% children.  At each stage, the node under consideration is expanded if its% weight is less than the squared distance to nearest currently known lattice% point.  This distance threshold is initially set to infinity.%% Because it is a depth-first traversal, we expand a node by computing its% first child.  If it is a leaf node, clearly it cannot be further expanded.% In this case, we will have found a closer lattice point than that previously% known. Therefore we can adaptively reduce the distance threshold to reflect% this new discovery.%% If the weight of the node under consideration is larger than this distance% threshold, then the current search path is terminated because it cannot% possibly lead to a closest lattice point. Upon path termination, the next% node to be considered is the next sibling of its parent.%% If xMax == 0, we do not apply (rectangular, or any) boundary control. In% other words, SEA_det behaves as a lattice decoder.  %% For more sophisticated operation, xMax may also be a vector of length m.% Then each node at the beginning of stage j in the tree, where the root node% is at the beginning of stage m and the leaf nodes are found at the end of% stage 1, has 2*xMax(j) children.  Equivalently, symbol xHat(j) is drawn from% {-xMax(j)+1,..,-1,0,1,..,xMax(j)}.%% If cplx == 1, we consider a tree of 2*m+1 levels with each node still having% 2*xMax children.  In addition, either xMax should be a complex-valued vector,% or imag(xMax) will be taken to be equal to real(xMax), i.e., a square QAM% constellation will be assumed by default.% % If either lattice reduction assistance or MMSE pre-processing are desired,% these operations should also be applied in advance of calling SEA_det.%% Notes:%% - Size(H,1) is expected to be equal to length(y).% - Size(H,1) is expected to be greater than or equal to size(H,2).% - Size(H,2) is expected to be equal to m.% - Length(xMax) is expected to be equal to either 1 or m.% - The solution xHat is an integer vector; be sure to apply any necessary%   scaling prior to calling SEA_det so that this solution is appropriate.%% Example:%%   m    = 4;                        % 4x4 MIMO system%   xMax = 2;                        % 16-QAM modulation%   cplx = 1;%   y    = randn(m,1)+i(randn(m,1);  % generate random complex target vector%   H    = randn(m,m)+i*randn(m,m);  % generate random complex channel %   [xHat,wHat,nv,nf,nl] = SEA_det(m,xMax,y,H,cplx);%% Version 1.1, copyright 2006 by Karen Su.%% Please send comments and bug reports to karen.su@utoronto.ca.%% Version 1.1%   Bug fix: now correctly handles xMax == 0 case.global w;global z;global cn;global zp;global nf;xHat = [];wHat = Inf;nv   = 0;nf   = 0;nl   = 0;%% A small number%EPS = 0.001;%% Basic error checking%[n,mChk] = size(H);if n ~= length(y) || mChk ~= m  fprintf('Error: Decoding failed, invalid dimensions for H.\n');  return;endif n < m  fprintf('Error: Cannot solve under-determined problem, n (%i) < m (%i).\n', n, m);  return;endif length(xMax) == 1  xMax = xMax*ones(m,1);elseif size(xMax,2) == m  xMax = xMax.';elseif size(xMax,1) ~= m  fprintf('Error: Decoding failed, invalid dimensions for xMax.\n');  return;end%% Complex -> real conversion if necessary%if cplx == 1  m = 2*m;  n = 2*n;  y = [real(y);imag(y)];  H = [[real(H),-imag(H)];[imag(H),real(H)]];  if isreal(xMax)    xMax = [xMax;xMax];  else    xMax = [real(xMax);imag(xMax)];  endend%% Special handling to allow xMax == 0%noBCind       = find(xMax==0);xMax(noBCind) = Inf;%% Reduce problem to square if H is overdetermined; also factorize code% generator%[Hq,Hr] = qr(H);wRoot   = 0;yR      = Hq'*y;if m < n  wRoot = norm(yR(m+1:n))^2;  yR    = yR(1:m);end%% A basic node data structure consists of%   w   : node weight%   pyR : parent's residual target vector, elements 1:dim  == py(1:dim,dim)%   zA  : accumulated symbol decision vector, length m-dim == z(dim+1:dim)%   dim : node/residual dimension, root (m+1) to leaf (1)%   cn  : sibling ordinal%   pw  : parent node weight                               == w(dim+1)%   ut  : (scalar) target for siblings at this level       == py(dim+1,dim)%   zp  : symbol decision of previous sibling             %% In addition, the following components enable us to effect more sophisticated,% albeit still justified rectangular, boundary control%   lb  : lower bound of admissible range for siblings at this level == lb(dim)%   ub  : upper bound of admissible range for siblings at this level == ub(dim)%% The algorithm requires only a fixed-size block of memory; we initialize it% with the root node.  %w   = zeros(1,m+1);py  = zeros(m,m);z   = zeros(1,m);dim = m;cn  = zeros(1,m);zp  = zeros(1,m);lb  = -xMax.'+1;ub  = xMax.';dimp    = dim+1;w(dimp) = wRoot;%% Compute first child of root node %py(1:dim,dim) = yR;                              % Store parent (root) residual target.compFirstChild(dim,dimp,lb(dim),ub(dim),Hr(dim,dim),py(dim,dim));backtrack = 0;while dim <= m  if w(dim) < wHat                     % If the node under consideration has a smaller weight    if dim == 1                        % and it is a leaf node, then update xHat, wHat       wHat = w(dim);      xHat = z;      nl   = nl + 1;      backtrack = 1;                   % To backtrack, we have to compute the next sibling      dim  = dimp;                     % of the current node's parent      dimp = dimp+1;      if cn(dim) <= ub(dim)-lb(dim)    % Check that there is at least one more sibling                         backtrack = 0;        compNextSibling(dim,dimp,lb(dim),ub(dim),Hr(dim,dim),py(dim,dim));      end      nf = nf + 1;    %    % If the node under consideration has a sufficiently small weight and is    % not a leaf node:    % - then either we are backtracking (backtrack == 1, and so compute the    %   next sibling of its parent)    %    elseif backtrack && cn(dim) > ub(dim)-lb(dim) % No more siblings      %backtrack = 1;      dim = dimp;      if dim <= m                      % Check that we have not backtracked to root        dimp = dimp+1;         if cn(dim) <= ub(dim)-lb(dim)  % Check that there is at least one more sibling          backtrack = 0;          compNextSibling(dim,dimp,lb(dim),ub(dim),Hr(dim,dim),py(dim,dim));        end        nf = nf + 1;      end      %    % - or we are trying an alternate path (backtrack == 0, and so compute    %   the first child)    %    else      %backtrack = 0;      nv   = nv + 1;      dimp = dim;      dim  = dim-1;      py(1:dim,dim) = py(1:dim,dimp)-Hr(1:dim,dimp)*z(dimp);  % Compute current node residual target.      nf            = nf + 2*dim;      compFirstChild(dim,dimp,lb(dim),ub(dim),Hr(dim,dim),py(dim,dim));    end  else                                 % If the node under consideration has too large a weight    dim       = dimp;                  % then we backtrack (if possible).  To do so, we have to    backtrack = 1;                     % compute the next sibling of the current node's parent.    if dim <= m                        % Check that we have not backtracked to root      dimp = dimp+1;      if cn(dim) <= ub(dim)-lb(dim)    % Check that there is at least one more sibling        backtrack = 0;        compNextSibling(dim,dimp,lb(dim),ub(dim),Hr(dim,dim),py(dim,dim));      end      nf = nf + 1;    end  end  nf = nf + 1;endxHat = xHat.';%   % Undo any complex -> real transformation that may have been done before%   if cplx == 1  m = m/2;  xHat = xHat(1:m)+i*xHat(m+1:2*m);endfunction compFirstChild(dim,dimp,lbd,ubd,Hrdd,pydd)global w;global z;global cn;global zp;global nf;z0 = pydd/Hrdd;                              % The first child is found byz1 = round(z0);                              % quantization and symbol-dependentz1 = min([z1 ubd]);                          % boundary control.z1 = max([z1 lbd]);z(dim)  = z1;                                % Store first child decisionzp(dim) = z0;                                % and pre-quantization data;w(dim)  = w(dimp)+(pydd-Hrdd*z(dim))^2;      % compute its weight/cost.cn(dim) = 1;                                 % First child ordinal has 1.nf      = nf + 6;function compNextSibling(dim,dimp,lbd,ubd,Hrdd,pydd)global w;global z;global cn;global zp;global nf;zn   = z(dim)-cn(dim)*sign(z(dim)-zp(dim));  % The next sibling symbol decision can beif zn > ubd                                  % derived from the current and previous ones,  zn = ubd-cn(dim);                          % followed by boundary control. This procedureelseif zn < lbd                              % is dependent on the child ordinal and also the  zn = lbd+cn(dim);                          % symbol-dependent lower and upper bounds.endzp(dim) = z(dim);                            % Save previous sibling's symbol decision andz(dim)  = zn;                                % store next sibling decision.cn(dim) = cn(dim)+1;                         % Siblings have one larger child ordinal.w(dim) = w(dimp)+(pydd-Hrdd*zn)^2;           % Compute sibling node weight.nf     = nf + 10;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -