├── BiGAMP ├── BiGAMP.m ├── BiGAMPOpt.m ├── BiGAMP_Aestim.m └── BiGAMP_Xestim.m ├── CVX_Optimal.m ├── Constell_Mapping.m ├── Constell_Modulate.m ├── GAMP_Bernoulli.m ├── GAMP_S.m ├── LICENSE ├── OthrerCS ├── QAm.m ├── SOMP2.m ├── cosamp.m └── rvmRegVb.m ├── Readme.md ├── SIMO_BiGAMP.m ├── SIMO_MessPass.m ├── SIMO_SVD.m ├── SIMO_S_MessPass.m ├── SIMO_X_MessPass.m ├── SIMO_algorithm.m ├── SIMO_result.txt ├── SIMO_test.m ├── S_BER.fig ├── TruboCS ├── BM3D_denoiser.m ├── Kernel_lin_1.m ├── dturbocs.m └── test.m ├── main.m ├── matlab.mat └── setup_DL.m /BiGAMP/BiGAMP.m: -------------------------------------------------------------------------------- 1 | function [xhat] = BiGAMP( opt, PrioriIn, optIn ) 2 | 3 | %% Setup why define these setting 4 | 5 | nitMin = opt.nitMin; % minimum number of iterations 6 | step = opt.step; % step size 7 | stepMin = opt.stepMin; % minimum step size 8 | stepMax = opt.stepMax; % maximum step size 9 | stepFilter = opt.stepFilter; % step filter setting, <1 for no effect 10 | adaptStep = opt.adaptStep; % adaptive step size 11 | stepIncr = opt.stepIncr; % step inc on succesful step 12 | stepDecr = opt.stepDecr; % step dec on failed step 13 | stepWindow = opt.stepWindow; % step size check window size 14 | tol = opt.tol; % Convergence tolerance 15 | stepTol = opt.stepTol; % minimum allowed step size 16 | maxBadSteps = opt.maxBadSteps; % maximum number of allowed bad steps 17 | maxStepDecr = opt.maxStepDecr; % amount to decrease maxStep after failures 18 | zvarToPvarMax = opt.zvarToPvarMax; % maximum zvar/pvar ratio 19 | 20 | 21 | 22 | %Get problem dimensions 23 | M = optIn.M; 24 | U = 1 ; 25 | L = optIn.L; 26 | nit = optIn.nit; 27 | % test 28 | Y = PrioriIn.Y; 29 | Sam = PrioriIn.Sam; 30 | QAM = PrioriIn.QAM; 31 | nuz = PrioriIn.ZVar; 32 | nuw = PrioriIn.noiseVar ; 33 | %Assign Avar and xvar mins 34 | xvarMin = opt.xvarMin; 35 | Avarmin = opt.AvarMin; 36 | state = []; 37 | 38 | %% Initialization 39 | 40 | B = randi([0,1], U * sqrt(QAM), L); 41 | B(:,1) = 1; 42 | xhat = Constell_Modulate(B, QAM); 43 | xvar = ones(U, L); 44 | Ahat = ones(M, U); 45 | Avar = nuz * ones(M, U); 46 | 47 | % xhat = zeros(U, L); 48 | % xvar = ones(U, L); 49 | % Ahat = nuz * randn(M, U); 50 | % Avar = nuz * ones(M, U); 51 | 52 | xhatBar = 0; 53 | AhatBar = 0; 54 | shat = 0; 55 | svar = 0; 56 | pvarOpt = 0; 57 | zvarOpt = 0 ; 58 | 59 | pvarMin = opt.pvarMin; 60 | 61 | %Placeholder initializations 62 | 63 | valOpt = []; 64 | val = zeros(nit.outer,1); 65 | zhatOpt = 0; 66 | 67 | 68 | %% Iterations 69 | 70 | %Start timing first iteration 71 | 72 | 73 | %Control variable to end the iterations 74 | stop = false; 75 | it = 0; 76 | failCount = 0; 77 | 78 | step1 = 1; 79 | valIn = -inf; 80 | % Main iteration loop 81 | while ~stop 82 | 83 | % Iteration count 84 | it = it + 1; 85 | 86 | % Check for final iteration 87 | if it >= nit.outer 88 | stop = true; 89 | end 90 | 91 | Ahat2 = abs(Ahat).^2; 92 | xhat2 = abs(xhat).^2; 93 | zvar = Avar*xhat2 + Ahat2*xvar; 94 | pvar = zvar + Avar*xvar; 95 | 96 | %Include pvar step ? 97 | pvar = step1*pvar + (1-step1)*pvarOpt; 98 | zvar = step1*zvar + (1-step1)*zvarOpt; 99 | 100 | %Update zhat 101 | zhat = Ahat * xhat; 102 | % Continued output step 103 | phat = zhat - shat.* zvar; 104 | 105 | % Compute log likelihood at the output and add it the total negative 106 | % K-L distance at the input. 107 | wvar_pos = max(1e-20, nuw); 108 | predErr = - ((abs(Y - phat).^2 ) + pvar./wvar_pos + log(wvar_pos)); 109 | 110 | valOut = sum(sum( predErr )); 111 | val(it) = valOut + valIn; 112 | 113 | % Determine if candidate passed 114 | if ~isempty(valOpt) 115 | 116 | %Check against worst value in last stepWindow good steps 117 | stopInd = length(valOpt); 118 | startInd = max(1,stopInd - stepWindow); 119 | 120 | %Check the step 121 | pass = (val(it) > min(valOpt(startInd:stopInd))) ||... 122 | ~adaptStep || (step <= stepMin); 123 | 124 | else 125 | pass = true; 126 | end 127 | 128 | % If pass, set the optimal values and compute a new target shat and 129 | % snew. 130 | if (pass) 131 | 132 | %Slightly inrease step size after pass if using adaptive steps 133 | step = stepIncr*step; 134 | 135 | 136 | % Set new optimal values 137 | shatOpt = shat; 138 | svarOpt = svar; 139 | xhatBarOpt = xhatBar; 140 | xhatOpt = xhat; 141 | AhatBarOpt = AhatBar; 142 | AhatOpt = Ahat; 143 | pvarOpt = pvar; 144 | zvarOpt = zvar; 145 | 146 | %Bound pvar 147 | pvar = max(pvar, pvarMin); 148 | 149 | %We keep a record of only the succesful step valOpt values 150 | valOpt = [valOpt val(it)]; %#ok 151 | 152 | 153 | % Compute posterior mean and variance 154 | %wvar = obj.wvar; 155 | gain = pvar./(pvar + nuw); 156 | zhat0 = gain.*(Y - phat) + phat; 157 | zvar0 = nuw.*gain; 158 | 159 | %Compute 1/pvar 160 | pvarInv = 1./pvar; 161 | 162 | shatNew = pvarInv.*(zhat0-phat); 163 | svarNew = pvarInv.*(1-min(zvar0./pvar,zvarToPvarMax)); 164 | 165 | %Enforce step size bounds 166 | step = min([max([step stepMin]) stepMax]); 167 | 168 | else 169 | %Check on failure count 170 | failCount = failCount + 1; 171 | if failCount > maxBadSteps 172 | failCount = 0; 173 | stepMax = max(stepMin,maxStepDecr*stepMax); 174 | end 175 | % Decrease step size 176 | step = max(stepMin, stepDecr*step); 177 | 178 | %Check for minimum step size 179 | if step < stepTol 180 | stop = true; 181 | end 182 | end 183 | 184 | % Check for convergence if step was succesful 185 | if pass 186 | if any(isnan(zhat(:))) || any(isinf(zhat(:))) 187 | stop = true; 188 | else 189 | %testVal = norm(zhat(:) - zhatOpt(:)) / norm(zhat(:)); 190 | testVal = norm(zhat(:) - zhatOpt(:)) / norm(zhat(:)); 191 | if (it > 1) && ... 192 | (testVal < tol) 193 | stop = true; 194 | end 195 | end 196 | 197 | end 198 | 199 | % Create new candidate shat 200 | if it > 1 201 | step1 = step; 202 | if stepFilter >= 1 203 | step1 = step1*it/(it+stepFilter); 204 | end 205 | end 206 | shat = (1-step1)*shatOpt + step1*shatNew; 207 | svar = (1-step1)*svarOpt + step1*svarNew; 208 | xhatBar = (1-step1)*xhatBarOpt + step1*xhatOpt; 209 | AhatBar = (1-step1)*AhatBarOpt + step1*AhatOpt; 210 | 211 | %Compute rvar and correct for infinite variance 212 | rvar = 1./((abs(AhatBar).^2)'*svar); 213 | rvar(rvar > opt.varThresh) = opt.varThresh; 214 | 215 | %Update rhat 216 | rGain = (1 - (rvar.*(Avar'*svar))); 217 | rGain = min(1,max(0,rGain)); 218 | rhat = xhatBar.*rGain + rvar.*(AhatBar'*shat); 219 | rvar = max(rvar, xvarMin); 220 | 221 | % Input linear step for A 222 | qvar = 1./(svar*(abs(xhatBar).^2)'); 223 | qvar(qvar > opt.varThresh) = opt.varThresh; 224 | 225 | %Update qhat 226 | qGain = (1 - (qvar.*(svar*xvar'))); 227 | qGain = min(1,max(0,qGain)); 228 | qhat = AhatBar.*qGain + qvar.*(shat*xhatBar'); 229 | qvar = max(qvar,Avarmin); 230 | 231 | % Input nonlinear step 232 | [xhat,xvar,valInX] = BiGAMP_Xestim(rhat, rvar, Sam); 233 | [Ahat,Avar,valInA] = BiGAMP_Aestim(qhat, qvar, nuz); 234 | 235 | 236 | valIn = sum( valInX(:) ) + sum ( valInA(:) ); 237 | 238 | 239 | %Don't stop before minimum iteration count 240 | if it < nitMin 241 | stop = false; 242 | end 243 | 244 | end 245 | 246 | 247 | %% Save the options object that was used 248 | 249 | %Estimates of the two matrix factors 250 | xhat = xhatOpt; 251 | % estFin.xvar = xvarOpt; 252 | % estFin.Ahat = AhatOpt; 253 | % estFin.Avar = AvarOpt; 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /BiGAMP/BiGAMPOpt.m: -------------------------------------------------------------------------------- 1 | classdef BiGAMPOpt 2 | % Options for the BiG-AMP optimizer. 3 | 4 | properties 5 | 6 | %***** General Options 7 | 8 | %Flag to control sparse mode. In sparse mode, the gOut object 9 | %should expect and return vectors containing only the observed 10 | %entries of Z. In sparse mode, rowLocations and columnLocations 11 | %must be set. In this mode, sparse matrix computations are used to 12 | %avoid storing full matrices of the MxL size. When the fraction of 13 | %observed entries is small, this will also result in a 14 | %computational savings. 15 | %Sparse mode requires you to first mex the support 16 | %function by executing: mex sparseMult2.c -largeArrayDims 17 | sparseMode = false; 18 | 19 | % Print progress 20 | verbose = false; 21 | 22 | %Return additional outputs useful for EM learning. Can be disabled 23 | %to reduce the memory required for the output structure 24 | saveEM = true; 25 | 26 | %Save diagnostic information. This option should only be used for 27 | %debugging purposes, as it will increase code run time. 28 | diagnostics = false; 29 | 30 | %Number of iterations 31 | nit = 1500; 32 | 33 | %Minimum number of iterations- sometimes useful with warm starting 34 | %approaches 35 | nitMin = 30; %0 for no effect 36 | 37 | %Specify a convergence tolerance. Iterations are terminated when 38 | %the norm of the differnece in two iterates divided by the norm of 39 | %the current iterate falls below this threshold. Set to -1 to 40 | %disable 41 | tol = 1e-8; 42 | 43 | %Error function. This is a function handle that acts on Zhat to 44 | %compute an NMSE error. 45 | error_function = @(q) inf; 46 | 47 | %Error functions for A and X 48 | error_functionA = @(q) inf; 49 | error_functionX = @(q) inf; 50 | error_functionX2 = @(q) inf; 51 | 52 | %Option to "normalize" variances for computation. May improve 53 | %robustness in some cases. Use not recommended. 54 | varNorm = false; 55 | 56 | 57 | %***** Initialization 58 | 59 | %Provide initial guesses for xhat0,xvar0,shat0. If these are set to 60 | %empty, then the appropriate method of the input estimator is 61 | %called to initialize these values. This functionality is useful 62 | %for warm starting the algorithm when not providing the full state. 63 | xhat0 = []; 64 | Ahat0 = []; 65 | xvar0 = []; 66 | Avar0 = []; 67 | shat0 = []; 68 | 69 | %These are used by the X2 variant of BiG-AMP 70 | x2hat0 = []; 71 | x2var0 = []; 72 | 73 | %***** Step Size Control 74 | 75 | %Logical flag to include a step size in the pvar/zvar calculation. 76 | %This momentum term often improves numerical performance. On by 77 | %defualt. 78 | pvarStep = true; 79 | 80 | %Initial step size, or fixed size for non-adaptive steps 81 | step = 0.05; 82 | 83 | % Enable adaptive step size 84 | adaptStep = true; 85 | 86 | % Disable computing the cost via Bethe free energy 87 | adaptStepBethe = false; 88 | 89 | % Minimum step size 90 | stepMin = 0.05; 91 | 92 | % Maximum step size 93 | stepMax = 0.5; 94 | 95 | % Multiplicative step size increase, when successful 96 | stepIncr = 1.1; 97 | 98 | % Multiplicative step size decrease, when unsuccessful 99 | stepDecr = 0.5; 100 | 101 | %Maximum number of allowed failed steps before we decrease stepMax, 102 | %inf for no effect 103 | maxBadSteps = inf; 104 | 105 | %Amount to decrease stepMax after maxBadSteps failed steps, 1 for 106 | %no effect 107 | maxStepDecr = 0.5; 108 | 109 | %Create a window for the adaptive step size test. Setting this to 110 | %zero causes it to have no effect. For postive integer values, 111 | %creats a moving window of this length when checking the step size 112 | %acceptance criteria. The new value is only required to be better 113 | %than the worst in this window, i.e. the step size criteria is not 114 | %required to monotonicaly increase. 115 | stepWindow = 1; 116 | 117 | % Iterations are termined when the step size becomes smaller 118 | % than this value. Set to -1 to disable 119 | stepTol = -1; 120 | 121 | %This is a filter value on the steps. It slows down the early steps 122 | %in a smooth way. Set to less than 1 for no effect, In particular, 123 | %the steps are computed as step1 = step*it/(it + stepFilter) 124 | stepFilter = 0; 125 | 126 | 127 | %***** Variance Control 128 | 129 | %Switch to enable uniform variance mode. Replaces all variances 130 | %with scalar approximations 131 | uniformVariance = false; 132 | 133 | %Minimum variances. See code for details of use. 134 | pvarMin = 1e-13; 135 | xvarMin = 0; 136 | AvarMin = 0; 137 | zvarToPvarMax = 0.99; % prevents negative svar, should be near 1 138 | 139 | %Variance threshold for rvar and qvar, set large for no effect 140 | varThresh = 1e6; 141 | 142 | %This was included for testing and should not be modified 143 | gainMode = 1; 144 | 145 | end 146 | 147 | methods 148 | 149 | % Constructor with default options 150 | function opt = BiGAMPOpt(varargin) 151 | if nargin == 0 152 | % No custom parameters values, thus create default object 153 | return 154 | elseif mod(nargin, 2) == 0 155 | % User is providing property/value pairs 156 | names = fieldnames(opt); % Get names of class properties 157 | 158 | % Iterate through every property/value pair, assigning 159 | % user-specified values. Note that the matching is NOT 160 | % case-sensitive 161 | for i = 1 : 2 : nargin - 1 162 | if any(strcmpi(varargin{i}, names)) 163 | % User has specified a valid property 164 | propName = names(strcmpi(varargin{i}, names)); 165 | opt.(propName{1}) = varargin{i+1}; 166 | else 167 | % Unrecognized property name 168 | error('BiGAMPOpt: %s is an unrecognized option', ... 169 | num2str(varargin{i})); 170 | end 171 | end 172 | return 173 | else 174 | error(['The BiGAMPOpt constructor requires arguments ' ... 175 | 'be provided in pairs, e.g., BiGAMPOpt(''adaptStep'',' ... 176 | ' false, ''nit'', 50)']) 177 | end 178 | end 179 | end 180 | 181 | end 182 | -------------------------------------------------------------------------------- /BiGAMP/BiGAMP_Aestim.m: -------------------------------------------------------------------------------- 1 | function [Ahat,Avar,val] = BiGAMP_Aestim(rhat, rvar, nuz) 2 | 3 | 4 | uhat0 = 0; 5 | uvar0 = nuz; 6 | 7 | % Compute posterior mean and variance 8 | gain = uvar0./(uvar0+rvar); 9 | Ahat = gain.*(rhat-uhat0)+uhat0; 10 | Avar = gain.*rvar; 11 | 12 | u1 = sum(Ahat(:))/numel(Ahat); 13 | v1 = sum(sum( abs(Ahat - u1*ones(size(Ahat))).^2 ))/numel(Ahat) +sum(Avar(:))/numel(Ahat); 14 | val = (log(v1./uvar0(1,1)) + (1-v1./uvar0(1,1)) ... 15 | - abs(u1-uhat0(1,1)).^2./uvar0(1,1) ); -------------------------------------------------------------------------------- /BiGAMP/BiGAMP_Xestim.m: -------------------------------------------------------------------------------- 1 | function [xhat,xvar,vall] = BiGAMP_Xestim(qhat, qvar, Sam) 2 | 3 | [U,L]=size(qhat); 4 | xhat=zeros(U,L); 5 | xvar=zeros(U,L); 6 | Pa=zeros(U,L,length(Sam)); 7 | P=zeros(U,L); 8 | uvar0 = 1; 9 | uhat0 = 0; 10 | %% 11 | for i = 1 : length(Sam) 12 | E = abs(Sam(1,i)*ones(U,L)-qhat).^2./qvar; 13 | Pa(:,:,i)=exp(-E); 14 | Pa = max(Pa,1e-200); 15 | P=P + Pa(:,:,i); 16 | end 17 | for i=1:4 18 | Pa(:,:,i)=Pa(:,:,i)./(P(:,:)); 19 | end 20 | %% 21 | % Compute posterior mean and variance 22 | for i=1 : length(Sam) 23 | xhat11 = Pa(:,:,i).*(Sam(1,i)*ones(U,L)); 24 | xhat = xhat+xhat11; 25 | end 26 | for i=1 : length(Sam) 27 | xvar11 = Pa(:,:,i).*(abs(Sam(1,i)*ones(U,L)-xhat).^2); 28 | xvar = xvar+xvar11; 29 | end 30 | 31 | xvar_over_uvar0 = qvar./(uvar0+qvar); 32 | vall = (log(xvar_over_uvar0) + (1-xvar_over_uvar0) ... 33 | - abs(xhat-uhat0).^2./uvar0 ); 34 | end 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /CVX_Optimal.m: -------------------------------------------------------------------------------- 1 | function theta_Opt = CVX_Optimal( G, Hd, Dh, rho, N) 2 | 3 | 4 | R = zeros(N+1 , N+1); 5 | R(1:N , :) = [ (rho^2 * Dh'* (G'* G) * Dh), (rho * Dh'* G'* Hd) ]; 6 | R( N+1 , :) = [ (rho * Hd'* G * Dh) , 0 ]; 7 | 8 | V = zeros(N+1 , N+1); 9 | V(1:N , 1:N) = rho*(1-rho)* diag(diag( (rho^2 * Dh'* (G'* G) * Dh) )); 10 | 11 | Pi = R + V ; 12 | 13 | %% 14 | cvx_begin sdp quiet 15 | variable Q(N+1,N+1) complex 16 | expression QQ(N+1, N+1) 17 | QQ = ( Q + Q' )./2; 18 | maximize( real(trace( Pi * QQ )) ) 19 | subject to 20 | QQ >= 0; 21 | vec( diag(QQ) ) == vec( ones(N + 1, 1) ); 22 | cvx_end 23 | [Uq, Dq, ~] = svd(QQ); 24 | 25 | A_Opt = 0; 26 | for iter = 1 : 1 27 | Rq = sqrt(0.5)*(randn(N+1, 1) + 1i*randn(N+1, 1)); 28 | theta = Uq * sqrt(Dq) * Rq ; 29 | theta = theta./(theta(N+1)); 30 | theta = theta(1:N)./(abs(theta(1:N))); 31 | A_ite = norm( G * Dh * theta , 'fro') ; 32 | if A_ite > A_Opt 33 | A_Opt = A_ite; 34 | theta_Opt = theta ; 35 | end 36 | end 37 | 38 | end 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Constell_Mapping.m: -------------------------------------------------------------------------------- 1 | function B = Constell_Mapping(A, qam, Sam) 2 | 3 | [M,N] = size(A); 4 | B = zeros(M*sqrt(qam), N); 5 | 6 | 7 | %% 8 | if qam == 4 9 | for m=1:M 10 | B((2*m-1),:) = real(A(m,:)); 11 | B((2*m),:) = imag(A(m,:)); 12 | end 13 | B(B>0) = 1; 14 | B(B<0) = 0; 15 | elseif qam == 16 16 | for n=1:N 17 | for m=1:M 18 | if A(m,n) == Sam(1) 19 | B((4*m-3),n) = 1; 20 | B((4*m-2),n) = 0; 21 | B((4*m-1),n) = 1; 22 | B((4*m),n) = 0; 23 | elseif A(m,n) == Sam(2) 24 | B((4*m-3),n) = 0; 25 | B((4*m-2),n) = 1; 26 | B((4*m-1),n) = 1; 27 | B((4*m),n) = 0; 28 | elseif A(m,n) == Sam(3) 29 | B((4*m-3),n) = 0; 30 | B((4*m-2),n) = 1; 31 | B((4*m-1),n) = 0; 32 | B((4*m),n) = 1; 33 | elseif A(m,n) == Sam(4) 34 | B((4*m-3),n) = 1; 35 | B((4*m-2),n) = 0; 36 | B((4*m-1),n) = 0; 37 | B((4*m),n) = 1; 38 | elseif A(m,n) == Sam(5) 39 | B((4*m-3),n) = 1; 40 | B((4*m-2),n) = 1; 41 | B((4*m-1),n) = 1; 42 | B((4*m),n) = 0; 43 | elseif A(m,n) == Sam(6) 44 | B((4*m-3),n) = 0; 45 | B((4*m-2),n) =1; 46 | B((4*m-1),n) = 1; 47 | B((4*m),n) = 1; 48 | elseif A(m,n) == Sam(7) 49 | B((4*m-3),n) = 0; 50 | B((4*m-2),n) = 0; 51 | B((4*m-1),n) = 0; 52 | B((4*m),n) = 1; 53 | elseif A(m,n) == Sam(8) 54 | B((4*m-3),n) = 1; 55 | B((4*m-2),n) = 0; 56 | B((4*m-1),n) = 0; 57 | B((4*m),n) = 0; 58 | elseif A(m,n) == Sam(9) 59 | B((4*m-3),n) = 1; 60 | B((4*m-2),n) = 1; 61 | B((4*m-1),n) = 1; 62 | B((4*m),n) = 1; 63 | elseif A(m,n)== Sam(10) 64 | B((4*m-3),n) = 0; 65 | B((4*m-2),n) = 0; 66 | B((4*m-1),n) = 1; 67 | B((4*m),n) = 1; 68 | elseif A(m,n) == Sam(11) 69 | B((4*m-3),n) = 0; 70 | B((4*m-2),n) = 0; 71 | B((4*m-1),n) = 0; 72 | B((4*m),n) = 0; 73 | elseif A(m,n) == Sam(12) 74 | B((4*m-3),n) = 1; 75 | B((4*m-2),n) = 1; 76 | B((4*m-1),n) = 0; 77 | B((4*m),n) = 0; 78 | elseif A(m,n) == Sam(13) 79 | B((4*m-3),n) = 1; 80 | B((4*m-2),n) = 0; 81 | B((4*m-1),n) = 1; 82 | B((4*m),n) = 1; 83 | elseif A(m,n) == Sam(14) 84 | B((4*m-3),n) = 0; 85 | B((4*m-2),n) = 0; 86 | B((4*m-1),n) = 1; 87 | B((4*m),n) = 0; 88 | elseif A(m,n) == Sam(15) 89 | B((4*m-3),n) = 0; 90 | B((4*m-2),n) = 1; 91 | B((4*m-1),n) = 0; 92 | B((4*m),n) = 0; 93 | else 94 | B((4*m-3),n) = 1; 95 | B((4*m-2),n) = 1; 96 | B((4*m-1),n) = 0; 97 | B((4*m),n) = 1; 98 | end 99 | end 100 | end 101 | end 102 | end 103 | 104 | -------------------------------------------------------------------------------- /Constell_Modulate.m: -------------------------------------------------------------------------------- 1 | function A = Constell_Modulate(B, qam) 2 | 3 | [M,N] = size(B); 4 | A = zeros(M/sqrt(qam), N); 5 | 6 | 7 | 8 | %% 9 | if qam == 4 10 | for n=1 : N 11 | for m=1 : M/sqrt(qam) 12 | pack=[B((2*m-1),n) B(2*m,n)]; 13 | if pack==[1 1] 14 | A(m,n)=1+1i; 15 | elseif pack==[0 1] 16 | A(m,n)=-1+1i; 17 | elseif pack==[0 0] 18 | A(m,n)=-1-1i; 19 | else 20 | A(m,n)=1-1i; 21 | end 22 | end 23 | end 24 | A = A./sqrt(2); 25 | elseif qam == 16 26 | for n=1 : N 27 | for m=1 : M/sqrt(qam) 28 | pack=[B((4*m-3),n) B((4*m-2),n) B((4*m-1),n) B(4*m,n)]; 29 | if pack == [1 0 1 0] 30 | A(m,n) = 1+1i; 31 | elseif pack == [0 1 1 0] 32 | A(m,n) = -1+1i; 33 | elseif pack == [0 1 0 1] 34 | A(m,n) = -1-1i; 35 | elseif pack == [1 0 0 1] 36 | A(m,n) = 1-1i; 37 | elseif pack == [1 1 1 0] 38 | A(m,n) = 3+1i; 39 | elseif pack == [0 1 1 1] 40 | A(m,n) = -1+3i; 41 | elseif pack == [0 0 0 1] 42 | A(m,n) = -3-1i; 43 | elseif pack == [1 0 0 0] 44 | A(m,n) = 1-3i; 45 | elseif pack == [1 1 1 1] 46 | A(m,n) = 3+3i; 47 | elseif pack == [0 0 1 1] 48 | A(m,n)=-3+3i; 49 | elseif pack == [0 0 0 0] 50 | A(m,n) = -3-3i; 51 | elseif pack == [1 1 0 0] 52 | A(m,n) = 3-3i; 53 | elseif pack == [1 0 1 1] 54 | A(m,n) = 1+3i; 55 | elseif pack == [0 0 1 0] 56 | A(m,n) = -3+1i; 57 | elseif pack == [0 1 0 0] 58 | A(m,n) = -1-3i; 59 | else 60 | A(m,n) = 3-1i; 61 | end 62 | end 63 | end 64 | A = A./sqrt(10); 65 | end 66 | end -------------------------------------------------------------------------------- /GAMP_Bernoulli.m: -------------------------------------------------------------------------------- 1 | function [ s_est ] = GAMP_Bernoulli( Y, A, nuw, rho, s ) 2 | 3 | % This is a message passing algorithm for compressed sensing problems with discrete variables (0,1). 4 | % The algorithm doesn't use these approximations in GAMP when combining the messages from check nodes to variable nodes, 5 | % but calculate these messages directly. So it slihtly outperforms the traditional GAMP in most cases. 6 | % Paramater setting: Y = Z + W = As + W ; 7 | % Y: observed signal; 8 | % A: sensing matrix; 9 | % s: true value; 10 | % W: noise~CN(0, nuw); 11 | %rho: the probability of s taken 1 ; 12 | % shat.m2n and svar.m2n are the mean and variance of s passed from check nodes to variable nodes 13 | % shat.m2n and svar.m2n are M*N*length(State) matrixes; the (m,n,i)th entry is the message from y_m to s_n when s_n taken as its i-th value(i.e., 0 or 1). 14 | % shat.n2m and svar.n2m are the mean and variance of s passed from variable nodes to check nodes. 15 | % shat.m2n and svar.m2n are M*N matrixes. the (m,n)th entry is the message from s_n to y_m. 16 | 17 | %% 18 | if nargin == 0 19 | clc 20 | %Problem dimensions 21 | optIn.M = 20; %number of observation signals 22 | optIn.N = 20; %number of detect signals 23 | rho = 0.5; 24 | 25 | A = sqrt(0.5)*(randn(optIn.M, optIn.N) + 1i*randn(optIn.M, optIn.N)) ; 26 | s = randi([0,1], optIn.N, 1); 27 | nuw = 1e-4 ; 28 | Y = A * s + nuw ; 29 | end 30 | 31 | [M, N] = size(A) ; 32 | State = [0, 1]; 33 | Prior_s = rho/(1-rho); % P_1/P_0 34 | % Initialization 35 | A2 = abs(A).^2 ; 36 | shat_m2n = zeros(M,N,length(State)) ; 37 | P_s2y = zeros( M, N, length(State)); 38 | shat_n2m = ones(M,N); 39 | for m = 1 : M 40 | p = randperm(N) ; 41 | shat_n2m(m , p(1: floor(N * (1 - rho)))) = 0; 42 | end 43 | svar_n2m = (rho - rho^2)*ones(M, N); 44 | Zvar = sum(A2 .* svar_n2m , 2) ; 45 | Zhat = sum(A .* shat_n2m , 2); 46 | 47 | stop = false; 48 | it = 1 ; 49 | nit = 20; 50 | amp_stop = 1e-8 ; 51 | %% 52 | while ~stop 53 | %% 54 | % message from check node to s_n 55 | % repmat(Y-Zhat,1,N)+A.*shat.n2m is the message from y_m to s_n after remove the exterior message from s_n to y_m. 56 | % [(Y-Zhat,1,N)+A.*shat.n2m]_{m,n} = A_{m,i}*s_i + w + As_{tilde};(s_{tilde}~CN(0,svar.n2m)) 57 | % the mean of A_{m,i}*s_i is [(Y-Zhat,1,N)+A.*shat.n2m]_{m,n}. 58 | for i = 1 : length(State) 59 | shat_m2n(:,:,i) = repmat(Y - Zhat , 1, N) - A .*( State(i) - shat_n2m) ; 60 | end 61 | svar_m2n = repmat( (repmat( nuw + Zvar, 1, N) - A2 .* svar_n2m ), 1, 1, length(State)); 62 | svar_m2n = max(svar_m2n, 1e-100); 63 | P_y2s = - abs(shat_m2n).^2 ./svar_m2n ; % log version log(P_dletas) 64 | % message from s_n to delta 65 | P_s = sum(P_y2s ,1); % posterior of s 66 | for m = 1 : M 67 | P_s2y(m,:,:) = P_s(1,:,:) - P_y2s(m,:,:); % remove exterior message 68 | end 69 | % avoid data overflow 70 | % Max_Ps2y = max(P_s2y,[], 3) ; 71 | % for i = 1 : N 72 | % P_s2y( Max_Ps2y(:,i) < -50, i, :) = -1 ; 73 | % end 74 | P1_P0 = P_s2y(:,:,2) - P_s2y(:,:,1) ; 75 | P1_P0 = max(min(P1_P0, 50 ), -50); 76 | P10_s2y = exp( P1_P0 ) ; % P1_s2y/P0_s2y 77 | % multily prior 78 | P10_s2y = P10_s2y * Prior_s ; 79 | % Normalization 80 | P_s2y (:,:,2) = P10_s2y ./(1 + P10_s2y); 81 | P_s2y(isnan(P_s2y)) = 1; % eps/eps=1; inf/inf =NaN 82 | P_s2y (:,:,1) = 1 - P_s2y (:,:,2); 83 | % Compute the mean and variance of message from s_n to y_m 84 | shat_old = shat_n2m ; 85 | shat_n2m = P_s2y (:,:,2) ; %the expectation of s is the probability of taking 1. 86 | svar_n2m = P_s2y(:,:,1).* P_s2y (:,:,2) ; %the expectation of s is rho*(1-rho). 87 | % Compute the mean and variance of z = As ; 88 | Zvar = sum(A2 .* svar_n2m , 2) ; 89 | Zhat = sum(A .* shat_n2m , 2); 90 | 91 | % Check for final iteration 92 | it = it + 1; 93 | % if (it >= nit)||(norm(shat_n2m - shat_old, 'fro')^2/M/N <= amp_stop) 94 | % stop = true; 95 | % end 96 | if (it >= nit) 97 | stop = true; 98 | end 99 | 100 | 101 | % Ps = reshape(P_s(1,:,:), N, length(State)); 102 | % [~,I] = max( Ps,[],2 ) ; 103 | % s_est = State( I )' ; 104 | % [~ , Serr] = biterr(s , s_est); 105 | % Serr 106 | % norm(Y-A*s)^2 107 | end 108 | log_Ps = reshape(P_s(1,:,:), N, length(State)); 109 | % Ps10 = max(min( ( log_Ps(:,2) - log_Ps(:,1)) , 50 ), -50); 110 | % Ps10 = exp( Ps10) ; % P_1/P_0 111 | % shat = Ps10./(1 + Ps10); % the expectation of s is the probability of taking 1. 112 | % shat(isnan(shat)) = 1; 113 | % svar = shat.*(1-shat) ; 114 | 115 | [~,I] = max( log_Ps,[],2 ) ; 116 | s_est = State( I )' ; 117 | % [~ , Serr] = biterr(s , s_est); 118 | % Serr 119 | % norm(Y-A*shat)^2/numel(Y) 120 | 121 | end 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /GAMP_S.m: -------------------------------------------------------------------------------- 1 | function [xhat] = GAMP_S(Y, A, nuw, rho, s ) 2 | 3 | %% 4 | [M, T] = size(Y); 5 | [~, K] = size(A); 6 | State = [0, 1] ; 7 | bata_shat = 0.1; 8 | bata_x = 0.2; 9 | 10 | %mean(A(:)) 11 | %% 12 | %gX = CAXwgnEstimIn(0,1); 13 | gOut = CAwgnEstimOut(Y, nuw); 14 | %gX = AwgnEstimOut(0.5, 0.25); 15 | 16 | xvar = rho*(1-rho)*ones(K, T); 17 | xhat= rho*ones(K, T); 18 | % xhat = ones(K,1); 19 | % p = randperm(K) ; 20 | % xhat(p(1: floor(K * (1 - rho)))) = 0; 21 | 22 | shat=zeros(size(Y)); % used for the tailor series expansion 23 | Ahat2 = abs(A).^2; 24 | xvarMin=0; 25 | zvarToPvarMax=0.99; 26 | N_amp=100; 27 | amp_diff_stop = 1e-10 ; 28 | 29 | svar = 0 ; 30 | rvar = 0 ; 31 | pvar = 0 ; 32 | rhat = 0 ; 33 | 34 | 35 | for it_gamp=1:N_amp 36 | zvar = Ahat2*xvar; 37 | 38 | % pvar_last = pvar ; 39 | pvar = zvar; 40 | % pvar = (1 - bata_shat) * pvar_last + bata_shat * pvar ; % damping 41 | 42 | zhat = A * xhat; 43 | phat = zhat- shat.*zvar; 44 | [zhat0,zvar0] = gOut.estim(phat,pvar); 45 | pvarInv = 1 ./ pvar; 46 | shat_last = shat ; 47 | shat = pvarInv.*(zhat0-phat); 48 | shat = (1 - bata_shat) * shat_last + bata_shat * shat ; % damping 49 | 50 | svar_last = svar ; 51 | svar = pvarInv.*(1-min(zvar0./pvar,zvarToPvarMax)); 52 | svar = (1 - bata_shat) * svar_last + bata_shat * svar ; % damping 53 | 54 | rvar_last = rvar ; 55 | rvar = 1./(Ahat2.'*svar); 56 | rvar = (1 - bata_shat) * rvar_last + bata_shat * rvar ; % damping 57 | 58 | rhat_last = rhat ; 59 | rhat = xhat + rvar.*(A'*shat); 60 | rhat = (1 - bata_shat) * rhat_last + bata_shat * rhat ; % damping 61 | 62 | rvar = max(rvar, xvarMin); 63 | xhat_old = xhat ; 64 | [xhat,xvar ] = Xestim(rhat, rvar ); 65 | % [xhat,xvar, ~ ] = gX.estim( rhat, rvar ) ; 66 | xhat = (1 - bata_x) * xhat_old + bata_x * xhat ; % damping 67 | if norm(xhat - xhat_old)^2/numel(xhat) < amp_diff_stop 68 | break; 69 | end 70 | end 71 | 72 | X_sam = zeros(K, T, length(State)) ; 73 | for i = 1 : length(State) 74 | X_sam(:,:, i) = abs( State(i) - xhat ); 75 | end 76 | [~, I] = min (X_sam, [], 3); 77 | xhat = State(I); 78 | 79 | % xhat = xhat(1:end-2); 80 | % xvar = xvar(1:end-2); 81 | 82 | end 83 | 84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yuan-Xiaojun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OthrerCS/QAm.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yuan-Xiaojun/Matlab_SIMO/81b4b867934770a589afc41857c1288b5181bfd5/OthrerCS/QAm.m -------------------------------------------------------------------------------- /OthrerCS/SOMP2.m: -------------------------------------------------------------------------------- 1 | function [supp,X] = SOMP2(Y,A,s) 2 | % Simulated Orthogona matching pursuit 3 | % works with unknown s 4 | % by J.C. Ye, 4/5/2012 5 | 6 | [m,n] = size(A); 7 | r = size(Y,2); 8 | X= zeros(n,r); 9 | % z = sum(abs(A).^2,1).^0.5; 10 | % A = A./z(ones(size(A,1),1),:); 11 | %% noise variance setup 12 | if nargin<4 13 | sigma =0; s_max = s; 14 | else 15 | s_max = m; 16 | end 17 | 18 | %% OMP step 19 | 20 | supp = []; 21 | supp_c = setdiff(1:n,supp); 22 | res = Y; 23 | 24 | while length(supp) < s % && norm(res(:)) > sigma 25 | supp_c = setdiff(1:n,supp); 26 | obs = sum(abs(res'*A(:,supp_c)).^2,1); 27 | [mval,midx] = max(obs); 28 | supp = union(supp,supp_c(midx)); 29 | [tmpU,R] = qr(A(:,supp),0); 30 | res= Y - tmpU*tmpU'*Y; 31 | end 32 | 33 | supp = sort(supp,'ascend'); 34 | X(supp, :) = pinv(A(:,supp))*Y; 35 | -------------------------------------------------------------------------------- /OthrerCS/cosamp.m: -------------------------------------------------------------------------------- 1 | function [Sest, t] = cosamp(Phi,u,K,tol,maxiterations) 2 | 3 | % Cosamp algorithm 4 | % Input 5 | % K : sparsity of Sest 6 | % Phi : measurement matrix 7 | % u: measured vector 8 | % tol : tolerance for approximation between successive solutions. 9 | % Output 10 | % Sest: Solution found by the algorithm 11 | % 12 | % Algorithm as described in "CoSaMP: Iterative signal recovery from 13 | % incomplete and inaccurate samples" by Deanna Needell and Joel Tropp. 14 | % 15 | 16 | 17 | % Initialization 18 | Sest = zeros(size(Phi,2),1); 19 | v = u; 20 | t = 1; 21 | numericalprecision = 1e-12; 22 | T = []; 23 | while (t <= maxiterations) && (norm(v)/norm(u) > tol) 24 | y = abs(Phi'*v); 25 | [vals,z] = sort(y,'descend'); 26 | Omega = find(y >= vals(2*K) & y > numericalprecision); 27 | T = union(Omega,T); 28 | b = pinv(Phi(:,T))*u; 29 | [vals,z] = sort(abs(b),'descend'); 30 | Kgoodindices = (abs(b) >= vals(K) & abs(b) > numericalprecision); 31 | T = T(Kgoodindices); 32 | Sest = zeros(size(Phi,2),1); 33 | b = b(Kgoodindices); 34 | Sest(T) = b; 35 | v = u - Phi(:,T)*b; 36 | t = t+1; 37 | end -------------------------------------------------------------------------------- /OthrerCS/rvmRegVb.m: -------------------------------------------------------------------------------- 1 | function [model, energy] = rvmRegVb(X, t, prior) 2 | % Variational Bayesian inference for RVM regression. 3 | % Input: 4 | % X: d x n data 5 | % t: 1 x n response 6 | % prior: prior parameter 7 | % Output: 8 | % model: trained model structure 9 | % energy: variational lower bound 10 | % Written by Mo Chen (sth4nth@gmail.com). 11 | [m,n] = size(X); 12 | if nargin < 3 13 | a0 = 1e-4; 14 | b0 = 1e-4; 15 | c0 = 1e-4; 16 | d0 = 1e-4; 17 | else 18 | a0 = prior.a; 19 | b0 = prior.b; 20 | c0 = prior.c; 21 | d0 = prior.d; 22 | end 23 | idx = (1:m)'; 24 | dg = sub2ind([m,m],idx,idx); 25 | I = eye(m); 26 | xbar = mean(X,2); 27 | tbar = mean(t,2); 28 | 29 | X = bsxfun(@minus,X,xbar); 30 | t = bsxfun(@minus,t,tbar); 31 | 32 | XX = X*X'; 33 | Xt = X*t'; 34 | 35 | maxiter = 400; 36 | energy = -inf(1,maxiter+1); 37 | tol = 1e-4; 38 | 39 | a = a0+1/2; 40 | c = c0+n/2; 41 | Ealpha = 1e-4; 42 | Ebeta = 1e-4; 43 | for iter = 2:maxiter 44 | % q(w) 45 | % invS = Ebeta*XX; 46 | % % diag(XX) 47 | invS = Ebeta*XX; 48 | invS(dg) = invS(dg) + Ealpha; 49 | % Ealpha 50 | % invS = invS+invS.'/2; 51 | invS(logical(eye(size(invS)))) = real(diag(invS)); 52 | invS = invS + 1e-4*eye(m); 53 | U = chol(invS); 54 | Ew = Ebeta*(U\(U'\Xt)); 55 | KLw = -sum(log(diag(U))); 56 | % q(alpha) 57 | % w2 = abs(Ew.*Ew); 58 | w2 = abs(Ew).^2; 59 | invU = U\I; 60 | dgS = dot(invU,invU,2); 61 | b = b0+0.5*(w2+dgS); 62 | Ealpha = a./b; 63 | KLalpha = -sum(a*log(b)); 64 | % q(beta) 65 | e2 = sum(abs(t-Ew'*X).^2); 66 | invUX = U\X; 67 | trXSX = real(dot(invUX(:),invUX(:))); 68 | d = d0+(e2+trXSX); 69 | Ebeta = c/d; 70 | KLbeta = -c*log(d); 71 | % lower bound 72 | energy(iter) = KLalpha+KLbeta+KLw; 73 | if energy(iter)-energy(iter-1) < tol*abs(energy(iter-1)); break; end 74 | end 75 | const = m*(gammaln(a)-gammaln(a0)+a0*log(b0))+gammaln(c)-gammaln(c0)+c0*log(d0)+0.5*(m-n*log(2*pi)); 76 | energy = energy(2:iter)+const; 77 | w0 = tbar-dot(Ew,xbar); 78 | 79 | model.w0 = w0; 80 | model.w = Ew; 81 | model.alpha = Ealpha; 82 | model.beta = Ebeta; 83 | model.a = a; 84 | model.b = b; 85 | model.c = c; 86 | model.d = d; 87 | model.xbar = xbar; -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Passive Beamforming and Information Transfer via Large Intelligent Surface 2 | 3 | This package contains the official implementation of the **passive beamforming method** and the **two-step signal detection methods** proposed in the paper: 4 | 5 | > W. Yan, X. Yuan and X. Kuai, "Passive Beamforming and Information Transfer via Large Intelligent Surface," *IEEE Wireless Communications Letters*, vol. 9, no. 4, pp. 533-537, Apr. 2020, doi: [10.1109/LWC.2019.2961670] (https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=8941126). 6 | 7 | ## Introduction 8 | 9 | This paper proposed a novel **passive beamforming and information transfer (PBIT)** technique by adopting spatial modulation on the index of the LIS (or RIS) elements, in which the LIS simultaneously enhances the primary communication (by passive beamforming) and sends its private data to the receiver (by spatial modulation). In this paper, we developed a passive beamforming method to improve the average receive signal-to-noise ratio (SNR), and established a two-step approach at the receiver to retrieve the information from both the transmitter and the LIS. 10 | 11 | 12 | ## Code Structure 13 | 14 | `main.m`: Set system parameters and output simulation results. 15 | 16 | `SIMO_algorithm`: Generate system model. 17 | 18 | `CVX_Optimal`: Optimize RIS phase shift. 19 | 20 | `Constell_Modulate` and `Constell_Mapping`: Constellation modulation and demodulation. 21 | 22 | `BiGAMP`: BiGAMP algorithm to detect user signals. 23 | 24 | `GAMP_Bernoulli`: GAMP algorithm to detect RIS data. 25 | 26 | `SIMO_result.txt`: Save the simulation results. 27 | 28 | ## Citation 29 | ``` 30 | @article{yan2019passive, 31 | title={Passive beamforming and information transfer via large intelligent surface}, 32 | author={Yan, Wenjing and Yuan, Xiaojun and Kuai, Xiaoyan}, 33 | journal={IEEE Wireless Communications Letters}, 34 | volume={9}, 35 | number={4}, 36 | pages={533--537}, 37 | month={Apr.} 38 | year={2020}, 39 | publisher={IEEE} 40 | } 41 | ``` 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SIMO_BiGAMP.m: -------------------------------------------------------------------------------- 1 | function results = SIMO_BiGAMP( optIn, PrioriIn ) 2 | 3 | %% 4 | M = optIn.M; 5 | N = optIn.N; 6 | L = optIn.L; 7 | nit = optIn.nit; 8 | 9 | A = PrioriIn.A; 10 | s = PrioriIn.s; 11 | rho = PrioriIn.rho ; 12 | X = PrioriIn.X; 13 | Hd = PrioriIn.Hd; 14 | Y = PrioriIn.Y; 15 | Sam = PrioriIn.Sam; 16 | State = PrioriIn.State; 17 | nuw = PrioriIn.noiseVar ; 18 | %% 19 | shat.nm = ones(M,N); 20 | for m = 1 : M 21 | p = randperm(N) ; 22 | shat.nm(m , p(1: floor(N * (1 - rho)))) = 0; 23 | end 24 | svar.nm = (rho - rho^2)*ones(M, N); 25 | 26 | %% BiGAMP estimate xhat 27 | 28 | opt = BiGAMPOpt; 29 | error_function = @(qval) 20*log10(norm(qval - Z,'fro') / norm(Z,'fro')); 30 | opt.error_function = error_function; 31 | 32 | [xhat] = BiGAMP(opt, PrioriIn, optIn ); 33 | 34 | phase = Sam(1)/xhat(1) ; 35 | xhat = phase * xhat ; 36 | X_sam = zeros(length(Sam), L) ; 37 | for i = 1 : length(Sam) 38 | X_sam(i,:) = abs( Sam(i) - xhat ); 39 | end 40 | [~,I] = min (X_sam); 41 | xhat = Sam(I); 42 | [~ , Xerr] = symerr(X , xhat); 43 | 44 | 45 | %% GAMP 46 | 47 | Zhat.mdelta = (Y * xhat')/L - Hd ; 48 | Zvar.mdelta = nuw/L ; 49 | [~, ~, P_s ] = SIMO_S_MessPass( Zhat, Zvar, shat, svar, optIn, PrioriIn ); 50 | 51 | %end 52 | %% 53 | % known shat 54 | % shat = s ; 55 | % zhat = A * shat + Hd ; 56 | % xhat = (zhat' * Y)/(zhat' * zhat); 57 | 58 | results.xhat = xhat; 59 | %results.shat = shat; 60 | results.Ps = reshape(P_s(1,:,:), N, length(State))'; 61 | 62 | end 63 | -------------------------------------------------------------------------------- /SIMO_MessPass.m: -------------------------------------------------------------------------------- 1 | function results = SIMO_MessPass( optIn, PrioriIn ) 2 | 3 | %% 4 | M = optIn.M; 5 | N = optIn.N; 6 | L = optIn.L; 7 | nit = optIn.nit; 8 | QAM = optIn.QAM; 9 | 10 | 11 | nuw = PrioriIn.noiseVar ; 12 | nuX = PrioriIn.nuX ; 13 | A = PrioriIn.A; 14 | Hd = PrioriIn.Hd; 15 | Y = PrioriIn.Y; 16 | Sam = PrioriIn.Sam; 17 | State = PrioriIn.State; 18 | 19 | % Y = pinv(A)*Y; 20 | % A = eye(M); 21 | 22 | %% 23 | A2 = abs(A).^2; 24 | Hd2 = abs(Hd).^2; 25 | 26 | stop = false; 27 | 28 | %shat = 0.5*ones(M,L,N); 29 | shat = randi([0,1],M, L, N); 30 | % for n = 1 : N 31 | % shat(:,:,n) = PrioriIn.s(n); 32 | % end 33 | % svar = zeros(M,L,N); 34 | shat2 = abs(shat).^2; 35 | svar = 0.25*ones(M,L,N); 36 | 37 | zhat = zeros(M,L); 38 | zvar = ones(M,L); 39 | pv1 = zeros(M,L); 40 | 41 | qvar = ones(M,L,length(Sam)); 42 | qhat = zeros(M,L,length(Sam)); 43 | Px2y = zeros(M,L,length(Sam)); 44 | 45 | rvar = ones(M,L,N,length(State)); 46 | rhat = zeros(M,L,N,length(State)); 47 | Ps2y = zeros(M,L,N,length(State)); 48 | 49 | % xhat = repmat(PrioriIn.X, M,1); 50 | % xhat2 = abs(xhat).^2; 51 | % xvar = zeros(M,L); 52 | 53 | it = 0; 54 | while ~stop 55 | 56 | it = it + 1; 57 | 58 | % Check for final iteration 59 | if it >= nit 60 | stop = true; 61 | end 62 | 63 | %% message passing between check node y and variable node x 64 | 65 | % % computate zhat zvar 66 | for m = 1 : M 67 | zhat(m, :) = A(m, :) * reshape(shat(m,:,:), L, N).' + Hd(m); 68 | zvar(m, :) = A2(m, :) * reshape(svar(m,:,:), L, N)'; 69 | end 70 | % computate Py2x 71 | for i = 1 : length(Sam) 72 | qvar(:,:,i) = zvar.*abs(Sam(i))^2; 73 | qhat(:,:,i) = Y - zhat.*Sam(i); 74 | end 75 | qvar = qvar + nuw; 76 | Py2x = - (log(qvar) + abs(qhat).^2 ./qvar); % log version log(Py2x) 77 | Px = sum(Py2x); % posterior of x 78 | for m = 1 : M 79 | Px2y(m,:,:) = Px(1,:,:) - Py2x(m,:,:); % log version log(Px2y) 80 | end 81 | %because the value of Px2y is too small, 82 | %so we multiply a mutual factor to provent the case of "NAN" arise. 83 | Px2y_min = max(Px2y,[], 3); 84 | for i = 1 : length(Sam) 85 | Px2y(:, :, i) = Px2y(:, :, i) - Px2y_min; 86 | end 87 | Px2y = exp(Px2y); 88 | % normailzed Px2y 89 | P_x = zeros(M,L); 90 | for i = 1 : length(Sam) 91 | P_x = P_x + Px2y(:,:,i); 92 | end 93 | % P_x = max(P_x, eps); 94 | for i = 1 : length(Sam) 95 | Px2y(:,:,i) = Px2y(:,:,i)./P_x; 96 | end 97 | % Compute the mean and variance of Px2y 98 | xhat = zeros(M,L); 99 | for i = 1 : length(Sam) 100 | xhati = Px2y(:,:,i).*(Sam(i).*ones(M,L)); 101 | xhat = xhat + xhati; 102 | end 103 | xvar = zeros(M,L); 104 | for i = 1 : length(Sam) 105 | xvari = Px2y(:,:,i).*(abs(Sam(i).*ones(M, L) - xhat).^2); 106 | xvar = xvar + xvari; 107 | end 108 | xhat2 = abs(xhat).^2; 109 | 110 | %% message passing between check node y and variable node s 111 | 112 | % computate phat pvar 113 | for m = 1 : M 114 | pv1(m, :) = A2(m, :) * reshape(shat2(m,:,:) + svar(m,:,:) , L, N)' + Hd2(m); 115 | end 116 | phat = zhat .* xhat; 117 | pvar = pv1.* xvar + zvar.*xhat2; 118 | % expand demension to dot product 119 | YN = repmat(Y, 1,1,N); 120 | phatN = repmat(phat, 1,1,N); 121 | pvarN = repmat(pvar, 1,1,N); 122 | xhatN = repmat(xhat, 1,1,N); 123 | xvarN = repmat(xvar, 1,1,N); 124 | xhat2N = repmat(xhat2, 1,1,N); 125 | AL = reshape(repmat(A,L,1), M,L,N); 126 | A2L = reshape(repmat(A2,L,1), M,L,N); 127 | 128 | % computate Py2s 129 | for i = 1 : length(State) 130 | rvar(:,:,:,i) = nuw + pvarN + A2L.*(abs(State(i))^2 ... 131 | - shat2 - svar).*xvarN - A2L.*svar.*xhat2N; 132 | 133 | rhat(:,:,:,i) = YN - phatN - AL.*(State(i) - shat).*xhatN; 134 | end 135 | Py2s = - (log(rvar) + abs(rhat).^2 ./rvar); % log version log(Py2s) 136 | Ps = sum(sum(Py2s, 1), 2); % posterior of s 137 | for m = 1 : M 138 | for l = 1 : L 139 | Ps2y(m,l,:,:) = Ps(1,1,:,:) - Py2s(m,l,:,:); % log version log(Ps2y) 140 | end 141 | end 142 | 143 | %Multiply a mutual factor to provent the case of "NAN" arise. 144 | %Ps2y = Ps2y/(M*L) ; 145 | Ps2y_min = max(Ps2y,[], 4); 146 | for i = 1 : length(State) 147 | Ps2y(:, :, :, i) = Ps2y(:, :, :, i) - Ps2y_min; 148 | end 149 | Ps2y = exp(Ps2y) ; 150 | 151 | % normailzed Ps2y 152 | P_s = zeros(M,L,N); 153 | for i = 1 : length(State) 154 | P_s = P_s + Ps2y(:,:,:,i); 155 | end 156 | %P_s = max(P_s, eps); 157 | for i = 1 : length(State) 158 | Ps2y(:,:,:,i) = Ps2y(:,:,:,i)./P_s; 159 | end 160 | % Compute the mean and variance of Ps2y 161 | shat = zeros(M,L,N); 162 | for i = 1 : length(State) 163 | shati = Ps2y(:,:,:,i).*(State(i).*ones(M,L,N)); 164 | shat = shat + shati; 165 | end 166 | svar = zeros(M,L,N); 167 | for i = 1 : length(State) 168 | svari = Ps2y(:,:,:,i).*(abs(State(i).*ones(M,L,N) - shat).^2); 169 | svar = svar + svari; 170 | end 171 | shat2 = abs(shat).^2; 172 | 173 | end 174 | results.Px = reshape(Px(1,:,:), L, length(Sam))'; 175 | results.Ps = reshape(Ps(1,1,:,:), N, length(State))'; 176 | 177 | end 178 | -------------------------------------------------------------------------------- /SIMO_SVD.m: -------------------------------------------------------------------------------- 1 | function results = SIMO_SVD( optIn, PrioriIn ) 2 | 3 | %% 4 | M = optIn.M; 5 | N = optIn.N; 6 | L = optIn.L; 7 | 8 | 9 | A = PrioriIn.A; 10 | s = PrioriIn.s; 11 | rho = PrioriIn.rho ; 12 | X = PrioriIn.X; 13 | Hd = PrioriIn.Hd; 14 | Y = PrioriIn.Y; 15 | Sam = PrioriIn.Sam; 16 | State = PrioriIn.State; 17 | nuw = PrioriIn.noiseVar ; 18 | %% 19 | shat.nm = ones(M,N); 20 | for m = 1 : M 21 | p = randperm(N) ; 22 | shat.nm(m , p(1: floor(N * (1 - rho)))) = 0; 23 | end 24 | svar.nm = (rho - rho^2)*ones(M, N); 25 | 26 | %% SVD estimate xhat 27 | % [~, ~, Vy] = svd(Y) ; 28 | % xhat = Vy(:,1)' ; 29 | % phase = Sam(1)/xhat(1) ; 30 | % xhat = phase * xhat ; 31 | % X_sam = zeros(length(Sam), L) ; 32 | % for i = 1 : length(Sam) 33 | % X_sam(i,:) = abs( Sam(i) - xhat ); 34 | % end 35 | % [~,I] = min (X_sam); 36 | % xhat = Sam(I); 37 | % [~ , Xerr] = symerr(X , xhat); 38 | 39 | % known xhat 40 | % xhat = X ; 41 | 42 | %% s=[0.5,0.25] 43 | % s1 = 0.5 * ones(N, 1); 44 | % zhat = A * s1 + Hd ; 45 | % xhat = (zhat' * Y)/(zhat' * zhat); 46 | % X_sam = zeros(length(Sam), L) ; 47 | % for i = 1 : length(Sam) 48 | % X_sam(i,:) = abs( Sam(i) - xhat ); 49 | % end 50 | % [~,I] = min (X_sam); 51 | % xhat = Sam(I); 52 | %[~ , Xerr] = symerr(X , xhat) 53 | 54 | 55 | %% BiGAMP estimate xhat 56 | 57 | opt = BiGAMPOpt; 58 | error_function = @(qval) 20*log10(norm(qval - Z,'fro') / norm(Z,'fro')); 59 | opt.error_function = error_function; 60 | 61 | [xhat] = BiGAMP(opt, PrioriIn, optIn ); 62 | 63 | phase = Sam(1)/xhat(1) ; 64 | xhat = phase * xhat ; 65 | X_sam = zeros(length(Sam), L) ; 66 | for i = 1 : length(Sam) 67 | X_sam(i,:) = abs( Sam(i) - xhat ); 68 | end 69 | [~,I] = min (X_sam); 70 | xhat = Sam(I); 71 | % [~ , Xerr] = symerr(X , xhat); 72 | 73 | %% OMP 74 | %Zhat = (Y * xhat')/L - Hd ; 75 | %[~,shat] = SOMP2(Zhat, A, floor(rho*N) ); 76 | %[model,~] = rvmRegVb(A.',Zhat.'); 77 | %[shat, t] = cosamp(A,Zhat, ceil(rho*N), 1e-3,50); 78 | %% GAMP 79 | 80 | Y_s = (Y * xhat')/L - Hd ; 81 | nuw_s = nuw/L ; 82 | [shat ] = GAMP_Bernoulli( Y_s, A, nuw_s, rho, s ); 83 | % [shat ] = GAMP_Bernoulli( Y_s, A, nuw_s, rho, s ); 84 | 85 | %% 86 | % known shat 87 | % shat = s ; 88 | % zhat = A * shat + Hd ; 89 | % xhat = (zhat' * Y)/(zhat' * zhat); 90 | 91 | results.xhat = xhat; 92 | results.shat = shat; 93 | 94 | end 95 | -------------------------------------------------------------------------------- /SIMO_S_MessPass.m: -------------------------------------------------------------------------------- 1 | function [shat, svar, P_s] = SIMO_S_MessPass( Zhat, Zvar, shat, svar, optIn, PrioriIn ) 2 | 3 | if nargin == 0 4 | clc 5 | 6 | %Problem dimensions 7 | optIn.M = 30; %coherence time 8 | optIn.N = 20; %transmit antenna 9 | optIn.L = 20; %received antenna why set in this way? 10 | 11 | PrioriIn.Sp_s = 1; 12 | PrioriIn.State = [0, 1]; 13 | 14 | PrioriIn.A = sqrt(0.5)*(randn(optIn.M, optIn.N) + 1i*randn(optIn.M, optIn.N)) ; 15 | PrioriIn.s = randi([0,1], optIn.N, 1); 16 | Zvar.mdelta = 1e-4 ; 17 | Zhat.mdelta = PrioriIn.A * PrioriIn.s + Zvar.mdelta ; 18 | optIn.nit.inner = 10 ; 19 | end 20 | M = optIn.M; 21 | N = optIn.N; 22 | nit = optIn.nit; 23 | 24 | A = PrioriIn.A; 25 | State = PrioriIn.State; 26 | Sp_s = PrioriIn.Sp_s; 27 | s = PrioriIn.s; 28 | rho = PrioriIn.rho ; 29 | A2 = abs(A).^2 ; 30 | shat.mn = zeros(M,N,length(State)) ; 31 | P_s2dleta = zeros( M, N, length(State)); 32 | 33 | shat.nm = ones(M,N); 34 | for m = 1 : M 35 | p = randperm(N) ; 36 | shat.nm(m , p(1: floor(N * (1 - rho)))) = 0; 37 | end 38 | svar.nm = (rho - rho^2)*ones(M, N); 39 | 40 | Zvar.deltam = sum(A2 .* svar.nm , 2) ; 41 | Zhat.deltam = sum(A .* shat.nm , 2); 42 | 43 | stop = false; 44 | it = 0 ; 45 | %% 46 | while ~stop 47 | 48 | it = it + 1; 49 | 50 | % Check for final iteration 51 | if it >= nit.inners 52 | stop = true; 53 | end 54 | %% 55 | % message from delta to s_n 56 | for i = 1 : length(State) 57 | shat.mn(:,:,i) = repmat(Zhat.mdelta - Zhat.deltam , 1, N) - A .*( State(i) - shat.nm) ; 58 | end 59 | svar.mn = repmat( (repmat(Zvar.mdelta + Zvar.deltam , 1, N) - A2 .* svar.nm ), 1, 1, length(State)); 60 | svar.mn = max(svar.mn, 1e-200); 61 | P_dleta2s = - (log(svar.mn) + abs(shat.mn).^2 ./svar.mn); % log version log(P_dletas) 62 | % message from s_n to delta 63 | P_s = sum(P_dleta2s ,1); % posterior of s 64 | for m = 1 : M 65 | P_s2dleta(m,:,:) = P_s(1,:,:) - P_dleta2s(m,:,:); % log version log(P_sdleta) 66 | end 67 | P10_s2dleta = min(max(exp( P_s2dleta(:,:,2) - P_s2dleta(:,:,1) ), eps), inf); 68 | % multily prior 69 | P10_s2dleta = P10_s2dleta * Sp_s ; 70 | % Normolization 71 | P_s2dleta (:,:,2) = P10_s2dleta ./(1 + P10_s2dleta); 72 | P_s2dleta(isnan(P_s2dleta)) = 1; 73 | P_s2dleta (:,:,1) = 1 - P_s2dleta (:,:,2); 74 | % Compute the mean and variance of P_sdleta 75 | shat.nm = zeros(M,N); 76 | for i = 1 : length(State) 77 | shati = P_s2dleta(:,:,i).*(State(i).*ones(M,N)); 78 | shat.nm = shat.nm + shati; 79 | end 80 | svar.nm = zeros(M,N); 81 | for i = 1 : length(State) 82 | svari = P_s2dleta(:,:,i).*(abs(State(i).*ones(M,N) - shat.nm).^2); 83 | svar.nm = svar.nm + svari; 84 | end 85 | % Compute the mean and variance of delta to m 86 | Zvar.deltam = sum(A2 .* svar.nm , 2) ; 87 | Zhat.deltam = sum(A .* shat.nm , 2); 88 | 89 | % Ps = reshape(P_s(1,:,:), N, length(State))'; 90 | % [~,I] = max( Ps ) ; 91 | % sh = State( I ) ; 92 | % cor_s = length(find((s - sh' ) ==0)); 93 | % Serr = (N - cor_s)/N 94 | % 95 | end 96 | % Ps = reshape(P_s(1,:,:), N, length(State))'; 97 | % [~,I] = max( Ps ) ; 98 | % sh = State( I ) ; 99 | % cor_s = length(find((s - sh' ) ==0)); 100 | % Serr = (N - cor_s)/N 101 | end -------------------------------------------------------------------------------- /SIMO_X_MessPass.m: -------------------------------------------------------------------------------- 1 | function [P_x2y1, P_x] = SIMO_X_MessPass( Zhat,Zvar, optIn, PrioriIn ) 2 | 3 | %% 4 | M = optIn.M; 5 | N = optIn.N; 6 | L = optIn.L; 7 | nit = optIn.nit; 8 | 9 | nuw = PrioriIn.noiseVar ; 10 | Hd = PrioriIn.Hd; 11 | Y = PrioriIn.Y; 12 | Sam = PrioriIn.Sam; 13 | C = length(Sam); 14 | X = PrioriIn.X; 15 | 16 | %% Initailization 17 | Sam2 = abs(Sam).^2 ; 18 | 19 | stop = false; 20 | 21 | P_x2y = ones(M, L, C)./C; 22 | xvar_ml = ones(M, L, C); 23 | xhat_ml = ones(M, L, C); 24 | 25 | %% 26 | it = 0; 27 | while ~stop 28 | 29 | it = it + 1; 30 | 31 | % Check for final iteration 32 | if it >= nit.innerx 33 | stop = true; 34 | end 35 | %% 36 | 37 | % message from y_ml to x_l 38 | for i = 1 : C 39 | xvar_ml(:,:,i) = nuw + Zvar.ml * Sam2(i) ; 40 | xhat_ml(:,:,i) = Y - (Zhat.ml + repmat(Hd, 1, L))* Sam(i) ; 41 | end 42 | P_y2x = - (log(xvar_ml) + abs(xhat_ml).^2 ./xvar_ml); % log version log(P_y2x) 43 | % message from x_l to y_ml 44 | P_x = sum(P_y2x, 1); % posterior of x 45 | for m = 1 : M 46 | P_x2y(m,:,:) = P_x(1,:,:) - P_y2x(m,:,:); % log version log(Px2y) 47 | end 48 | % Multiply a mutual factor to provent the case of "NAN" arise. 49 | Px2y_max = max(P_x2y,[], 3); 50 | for i = 1 : length(Sam) 51 | P_x2y(:, :, i) = P_x2y(:, :, i) - Px2y_max; 52 | end 53 | P_x2y = exp(P_x2y) ; 54 | % Normolization 55 | P_sum = zeros(M,L); 56 | for i = 1 : length(Sam) 57 | P_sum = P_sum + P_x2y(:,:,i); 58 | end 59 | % P_x = max(P_x, eps); 60 | for i = 1 : length(Sam) 61 | P_x2y(:,:,i) = P_x2y(:,:,i)./P_sum; 62 | end 63 | 64 | end 65 | [~,b] = max(P_x2y(1,1,:)); % eliminate ambiguity 66 | P_x2y1 = zeros( size(P_x2y)); 67 | for i = 1 : C 68 | col = mod((i + b - 1), 4); 69 | if col == 0 70 | col = 4; 71 | end 72 | P_x2y1(:,:,i) = P_x2y(:,:, col ); 73 | end 74 | 75 | % xhat = zeros(M,N); 76 | % for i = 1 : length(Sam) 77 | % xhati = P_x2y1(:,:,i).*(Sam(i).*ones(M,N)); 78 | % xhat = xhat + xhati; 79 | % end 80 | % xvar = zeros(M,N); 81 | % for i = 1 : length(Sam) 82 | % xvari = P_x2y1(:,:,i).*(abs(Sam(i).*ones(M,N) - xhat).^2); 83 | % xvar = xvar + xvari; 84 | % end 85 | end 86 | -------------------------------------------------------------------------------- /SIMO_algorithm.m: -------------------------------------------------------------------------------- 1 | function results = SIMO_algorithm(optIn) 2 | 3 | 4 | %% 5 | M = optIn.M; 6 | N = optIn.N; 7 | L = optIn.L; 8 | SNR = optIn.SNR; 9 | QAM = optIn.QAM; 10 | State = [0,1]; 11 | rho = optIn.rho; 12 | Sp_s = rho/(1-rho) ; % P1/P0 13 | beta = 0.5; % fadding factor 14 | %% produce System model 15 | 16 | if QAM == 4 17 | Sam = [1+1i -1+1i -1-1i 1-1i]./sqrt(2); 18 | elseif QAM == 16 19 | Sam = [1+1i -1+1i -1-1i 1-1i 3+1i -1+3i -3-1i 1-3i 3+3i -3+3i -3-3i 3-3i 1+3i -3+1i -1-3i 3-1i]./sqrt(10); 20 | end 21 | 22 | G = sqrt(0.5)*(randn(M,N) + 1i*randn(M,N)); 23 | Hd = sqrt(0.5)*(randn(M, 1) + 1i*randn(M, 1)); 24 | Hr = sqrt(0.5)*(randn(N, 1) + 1i*randn(N, 1)); 25 | Dh = diag(Hr); 26 | theta = CVX_Optimal( G, Hd, Dh, rho, N); 27 | %theta = randn(N,1) + 1i*randn(N,1); 28 | %theta = theta ./(abs(theta)); 29 | A = beta * G * diag(theta) * Dh ; 30 | % Produce RIS data 31 | s = ones(N,1); 32 | p = randperm(N) ; 33 | s(p(1: floor(N * (1 - rho)))) = 0; 34 | % Produce user signal 35 | B = randi([0,1], sqrt(QAM), L); 36 | B(:,1) = 1; 37 | % X = bi2de(B','left-msb'); 38 | % X = qammod(X, QAM).'; 39 | % X = X./abs(X(1)) ; 40 | X = Constell_Modulate(B, QAM); 41 | nuz = 1 + N * beta* rho * 0.5 ; 42 | nuw = 10^(-SNR/10) ; 43 | Z = (A*s + Hd) * X ; 44 | Y = Z + sqrt(nuw/2)*(randn(size(Z))+1i*randn(size(Z))) ; 45 | 46 | %% Initialize results as empty 47 | results = []; 48 | PrioriIn.noiseVar = nuw; 49 | PrioriIn.ZVar = nuz; 50 | PrioriIn.nuX = 1; 51 | PrioriIn.A = A; 52 | PrioriIn.X = X; 53 | PrioriIn.Hd = Hd; 54 | PrioriIn.Y = Y; 55 | PrioriIn.Sam = Sam; 56 | PrioriIn.QAM = QAM; 57 | PrioriIn.State = State ; 58 | PrioriIn.Sp_s = Sp_s ; 59 | PrioriIn.rho = rho ; 60 | 61 | PrioriIn.s = s; 62 | PrioriIn.X = X; 63 | %% 64 | 65 | % [results1] = SIMO_MessPass( optIn, PrioriIn ); 66 | %[results1] = SIMO_test( optIn, PrioriIn ); 67 | [results1] = SIMO_SVD( optIn, PrioriIn ); 68 | 69 | xhat = results1.xhat ; 70 | shat = results1.shat ; 71 | 72 | 73 | %% 74 | Bhat = Constell_Mapping(xhat, QAM, Sam) ; 75 | % Bhat = qamdemod(xhat, QAM); 76 | % Bhat = de2bi(Bhat,'left-msb'); 77 | [~ , Xerr] = biterr(B , Bhat); 78 | [~ , Serr] = biterr(s , shat ); 79 | 80 | results.Xerr = Xerr ; 81 | results.Serr = Serr ; 82 | 83 | 84 | 85 | end 86 | %% 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /SIMO_result.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | SimLen = 10, M = 32, N = 16, L = 100, QAM = 4 4 | SNR =-20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 5 | X_BER =1.545000e-01 2.750000e-02 6.950000e-02 2.000000e-02 4.000000e-03 5.000000e-04 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 6 | S_BER =2.375000e-01 9.375000e-02 1.562500e-01 5.625000e-02 2.500000e-02 2.500000e-02 3.750000e-02 1.875000e-02 4.375000e-02 1.875000e-02 1.875000e-02 7 | 8 | SimLen = 10, M = 32, N = 16, L = 100, QAM = 4 9 | SNR =-20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 10 | X_BER =9.400000e-02 9.200000e-02 7.950000e-02 7.500000e-03 5.500000e-03 0.000000e+00 2.000000e-03 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 11 | S_BER =1.250000e-01 1.625000e-01 1.625000e-01 6.875000e-02 2.500000e-02 3.750000e-02 1.875000e-02 1.875000e-02 5.000000e-02 1.250000e-02 1.875000e-02 12 | -------------------------------------------------------------------------------- /SIMO_test.m: -------------------------------------------------------------------------------- 1 | function results = SIMO_test( optIn, PrioriIn ) 2 | 3 | %% 4 | M = optIn.M; 5 | N = optIn.N; 6 | L = optIn.L; 7 | nit = optIn.nit; 8 | 9 | nuw = PrioriIn.noiseVar ; 10 | A = PrioriIn.A; 11 | Hd = PrioriIn.Hd; 12 | Y = PrioriIn.Y; 13 | Sam = PrioriIn.Sam; 14 | C = length(Sam); 15 | State = PrioriIn.State; 16 | s = PrioriIn.s; 17 | X = PrioriIn.X; 18 | Z = A*s ; 19 | % Step = 0.1; 20 | % StepInc = 1.1; 21 | % StepDec = 0.5; 22 | % StepMin = 0.01; 23 | % StepMax = 0.99; 24 | % DampOpt = 0; 25 | %% Initailization 26 | A2 = abs(A).^2; 27 | Sam2 = abs(Sam).^2 ; 28 | 29 | stop = false; 30 | 31 | P_x2y = ones(M, L, C)./C; % Initailize p_{l,m}^i 32 | % P_x2y = zeros(M, L, C); 33 | % for l = 1 : L 34 | % [~,c] = min(X(l) - Sam); 35 | % P_x2y(:,l,c) = 1 ; 36 | % end 37 | 38 | % shat.nm = 0.5*ones(M, N); 39 | % svar.nm = ones(M, N); 40 | shat.nm = randi([0,1], M, N); 41 | svar.nm = 0.25*ones(M, N); 42 | % shat.nm = repmat(s', M, 1); 43 | % svar.nm = zeros(M, N); 44 | 45 | % Initailize Z_mean, Z_var keep static during the algorithm. 46 | Z_mean = zeros(M,L,C); 47 | Z_var = nuw*ones(M,L,C); 48 | for i = 1 : C 49 | Z_mean(:,:,i) = Y/Sam(i) ; 50 | Z_var(:,:,i) = Z_var(:,:,i)/Sam2(i) ; 51 | end 52 | for m = 1 : M 53 | Z_mean(m,:,:) = Z_mean(m,:,:) - Hd(m) ; 54 | end 55 | % Initailize Zvar.deltam, Zhat.deltam. 56 | Zvar.deltam = sum(A2 .* svar.nm , 2); 57 | Zhat.deltam = sum(A .* shat.nm , 2); 58 | 59 | 60 | %% 61 | it = 0; 62 | while ~stop 63 | 64 | it = it + 1; 65 | 66 | % Check for final iteration 67 | if it >= nit.outer 68 | stop = true; 69 | end 70 | %% 71 | % message from y_ml to Z_m 72 | for i = 1 : C 73 | P_x2y(:,:,i) = P_x2y(:,:,i)/Sam2(i) ; 74 | end 75 | Pxs = sum(P_x2y, 3); 76 | for i = 1 : C 77 | P_x2y(:,:,i) = P_x2y(:,:,i)./Pxs ; 78 | end 79 | 80 | Zhat.lm = reshape(sum(P_x2y.*Z_mean, 3), M, L); 81 | Zvar.lm = abs(Z_mean - repmat(Zhat.lm, 1, 1, C)).^2 + Z_var; 82 | Zvar.lm = reshape(sum(P_x2y.*Zvar.lm, 3), M, L); 83 | Zvar.lm1 = 1./Zvar.lm ; 84 | Zmse.lm = abs(norm(Z - Zhat.lm,'fro'))^2 /abs(norm(Z,'fro'))^2 ; 85 | % message from z_m to delta 86 | Zvar.mdelta1 = reshape(sum(Zvar.lm1, 2), M, 1) ; 87 | Zhat.mdelta = reshape(sum(Zhat.lm .* Zvar.lm1, 2), M, 1)./Zvar.mdelta1 ; 88 | Zvar.mdelta = 1./Zvar.mdelta1 ; 89 | Zmse.mdelta = abs(norm(Z - Zhat.mdelta,'fro'))^2 /abs(norm(Z,'fro'))^2 ; 90 | %% 91 | 92 | % if (it > 1) 93 | % Damp = abs(norm(Y - (Zhat.deltam + Hd )* (sum(xhat, 1)/M) ,'fro'))^2 ; 94 | % + sum(Zvar.deltam(:)) + sum(xvar(:))/M 95 | % if ( Damp > DampOpt ) 96 | % Step = Step * StepDec ; 97 | % else 98 | % Step = Step * StepInc ; 99 | % end 100 | % Step = min( max(Step, StepMin ), StepMax); 101 | % DampOpt = Damp ; 102 | % if it == 2 103 | % Step = 0; 104 | % end 105 | % if it == 3 106 | % Step = 1; 107 | % end 108 | % if Damp < nuw*M*L 109 | % stop = true; 110 | % end 111 | % Zvar.deltam = Zvar.deltam * Step + Zvar.deltamOpt * (1 - Step) ; 112 | % Zhat.deltam = Zhat.deltam * Step + Zhat.deltamOpt * (1 - Step) ; 113 | % end 114 | %% GAMP module to estimate s 115 | 116 | [shat, svar, P_s] = SIMO_S_MessPass( Zhat, Zvar, shat, svar, optIn, PrioriIn ); 117 | 118 | %% 119 | % message from delta to z_m 120 | Zvar.deltamOpt = Zvar.deltam ; 121 | Zhat.deltamOpt = Zhat.deltam ; 122 | 123 | Zvar.deltam = sum(A2 .* svar.nm , 2); 124 | Zhat.deltam = sum(A .* shat.nm , 2); 125 | Zvar.deltam1 = min(1./Zvar.deltam, inf) ; 126 | Zmse.deltam = abs(norm(Z - Zhat.deltam,'fro'))^2 /abs(norm(Z,'fro'))^2 ; 127 | % message from z_m to y_ml 128 | Zhat.lm1 = Zhat.lm .* Zvar.lm1 ; 129 | for l = 1 : L 130 | Zvar.ml1(:,l) = Zvar.mdelta1 - Zvar.lm1(:,l) + Zvar.deltam1 ; 131 | Zhat.ml(:,l) = ( Zhat.mdelta .* Zvar.mdelta1 - Zhat.lm1(:,l) + Zhat.deltam.*Zvar.deltam1 )./Zvar.ml1(:,l) ; 132 | end 133 | Zvar.ml = max(1./Zvar.ml1, 1e-200) ; 134 | Zmse.ml = abs(norm(Z - Zhat.ml,'fro'))^2 /abs(norm(Z,'fro'))^2 ; 135 | %% GAMP module to estimate X 136 | 137 | [P_x2y, P_x] = SIMO_X_MessPass( Zhat,Zvar, optIn, PrioriIn ) ; 138 | P_x = reshape(P_x(1,:,:), L, length(Sam))'; 139 | [~,I] = max( P_x ) ; 140 | xhat = Sam( I ) ; 141 | [~ , Xerr] = symerr(X , xhat) 142 | end 143 | 144 | % P_x = reshape(P_x(1,:,:), L, length(Sam))'; 145 | % [~,I] = max( P_x ) ; 146 | % xhat = Sam( I ) ; 147 | 148 | results.xhat = xhat; 149 | results.Ps = reshape(P_s(1,:,:), N, length(State))'; 150 | 151 | % [~,I] = max( results.Px ) ; 152 | % xhat1 = Sam( I ) ; 153 | % cor_x = length(find((X-xhat1)==0)); 154 | % Xerr = ( L - cor_x)/( L) ; 155 | % 156 | % [~,I] = max( results.Ps ) ; 157 | % sh = State( I ) ; 158 | % cor_s = length(find((s - sh' ) ==0)); 159 | % Serr = (N - cor_s)/N 160 | 161 | end 162 | -------------------------------------------------------------------------------- /S_BER.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yuan-Xiaojun/Matlab_SIMO/81b4b867934770a589afc41857c1288b5181bfd5/S_BER.fig -------------------------------------------------------------------------------- /TruboCS/BM3D_denoiser.m: -------------------------------------------------------------------------------- 1 | %denoiser using BM3D 2 | %you should install bm3d first 3 | function [F,F_div] = BM3D_denoiser(y,v) 4 | [m,n]=size(y); 5 | % if m~=n 6 | % if floor(sqrt(m*n))-sqrt(m*n)~=0 7 | % else 8 | % n=sqrt(m*n); 9 | % k=reshape(y,n,n); 10 | % end 11 | % else 12 | % k=y; 13 | % end 14 | 15 | n=sqrt(m*n); 16 | % y=reshape(y,n,n); 17 | denoiser='fast-BM3D'; 18 | %denoiser='BM3D'; 19 | denoi=@(noisy,sigma_hat) denoise(noisy,sigma_hat,n,n,denoiser); 20 | 21 | % denoised=denoi(y,v); 22 | % eta=randn(1,n^2); 23 | % epsilon=max(y)/1000+eps; 24 | % div=eta*((denoi(y+epsilon*eta',v)-denoised)/epsilon)/n^2; 25 | 26 | % [~,y_hat]=BM3D(1,k,v,'np',0); 27 | % xhat = obj.fxnDenoise(rhat,rvar); 28 | denoised=denoi(y,v); 29 | div=0; 30 | K=1; 31 | for ii=1:K 32 | %epsilon = 0.05*min(v, mean(abs(y),1)) + eps; 33 | epsilon=max(y)/100+eps; 34 | %eta = sign(randn(1,n^2)); % random direction 35 | eta=randn(1,n^2); 36 | rhat_perturbed = y + epsilon*eta'; 37 | xhat_perturbed=denoi(rhat_perturbed,v); 38 | divp=eta*(xhat_perturbed-denoised)/epsilon; 39 | div=div+divp; 40 | end 41 | div=div/K/n^2; 42 | 43 | 44 | % de_type='lc';%lc,np 45 | % [~,y_hat]=BM3D(1,k,v,de_type,0); %fast BM3D 46 | % y_hat=y_hat*255; 47 | % eta=randn(n,n); 48 | % epsilon=max(y)/1000+eps; 49 | % [~,y_hat1]=BM3D(1,k+epsilon*eta,v,de_type,0); 50 | % y_hat1=y_hat1*255; 51 | % F_div=sum(sum(eta.*((y_hat1-y_hat)/epsilon)))/n^2; 52 | % F=reshape(y_hat,1,n^2); 53 | 54 | F=reshape(denoised,1,n^2); 55 | F_div=div; 56 | end -------------------------------------------------------------------------------- /TruboCS/Kernel_lin_1.m: -------------------------------------------------------------------------------- 1 | %-------------------------------------------------------------------------- 2 | % First kind of piece-wise linear function. See 3 | % "Near Optimal compressed sensing without priors: parametric SURE approximate 4 | % message passing" 5 | 6 | % F: 3 * N 7 | % F_div: 3 * 1 8 | % y: N * 1 9 | %-------------------------------------------------------------------------- 10 | function [F,F_div] = Kernel_lin_1(y, v) 11 | 12 | 13 | alpha_1 = 2 * sqrt(v); % see (20) in the above paper 14 | alpha_2 = 4 * sqrt(v); 15 | 16 | if(alpha_2 / alpha_1 ~= 2 ) 17 | % fprintf('the denoisers are different from the paper if alpha_2/alpha_1!=2\n'); 18 | end 19 | 20 | N = length(y); 21 | y = reshape(y, 1, N); 22 | 23 | %--------------------------------------------- 24 | % The endpoints of the line segments 25 | % See the figure 26 | %--------------------------------------------- 27 | 28 | index_1 = find( y < - alpha_2); 29 | index_2 = find( y > -alpha_2 & y < -alpha_1 ); 30 | index_3 = find( y > -alpha_1 & y < alpha_1 ); 31 | index_4 = find( y > alpha_1 & y < alpha_2 ); 32 | index_5 = find( y > alpha_2 ); 33 | 34 | 35 | if v==0 36 | F_div(1) = 0; 37 | F_div(2) = 0; 38 | F_div(3) = 1; 39 | F(1,:) = zeros(1,N); 40 | F(2,:) = zeros(1,N); 41 | f3 = zeros(1,N); 42 | f3(index_1) = y(index_1) + alpha_2; 43 | f3(index_5) = y(index_5) - alpha_2; 44 | F(3,:) = f3; 45 | else 46 | % function 1 47 | f1 = zeros(1,N); 48 | f1(index_2) = -1/alpha_1 * y(index_2) - 2; 49 | f1(index_3) = 1/alpha_1 * y(index_3); 50 | f1(index_4) = -1/alpha_1 * y(index_4) + 2; 51 | 52 | % function 2 53 | f2 = zeros(1,N); 54 | f2(index_1) = -1; 55 | f2(index_2) = ( y(index_2) + alpha_1 ) / ( alpha_2 - alpha_1 ); 56 | f2(index_3) = 0; 57 | f2(index_4) = ( y(index_4) - alpha_1 ) / ( alpha_2 - alpha_1 ); 58 | f2(index_5) = 1; 59 | 60 | % function 3 61 | f3 = zeros(1,N); 62 | f3(index_1) = y(index_1) + alpha_2; 63 | f3(index_5) = y(index_5) - alpha_2; 64 | 65 | F(1,:) = f1; 66 | F(2,:) = f2; 67 | F(3,:) = f3; 68 | 69 | %----------------------------------------------------- 70 | % Divergence, namely, the sum of derivatives 71 | %----------------------------------------------------- 72 | F_div(1) = 1/N * ( -1/alpha_1 * length(index_2) + 1/alpha_1 * length(index_3) -1/alpha_1 * length(index_4) ); 73 | F_div(2) = 1/N * ( 1/( alpha_2 - alpha_1 ) * length(index_2) + 1/( alpha_2 - alpha_1 ) * length(index_4) ); 74 | F_div(3) = 1/N * ( length(index_1) + length(index_5) ); 75 | end 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /TruboCS/dturbocs.m: -------------------------------------------------------------------------------- 1 | % OAMP_KERNEL_DCT FUNCTION (!!!fast computation version!!!) 2 | % According to algorithm OAMP 3 | % this function should be applied to Orthogonal matrix A for we can use 4 | % fast algorithm. We assume the measurement matrix have been row normalized 5 | % to one. 6 | % we should know the row choosen by measurement matrix. 7 | function [errx_out,x_hat]=dturbocs(y,p,M,N,K,index,sigma,errx) 8 | % input signal: y 9 | % measurement matrix: A 10 | % w=At*(A*At)^(-1); 11 | % a=(n^2)/trace(w*A); 12 | % AG=a*w; 13 | % inverse matrix: AG; 14 | % trace of At*A: TRA 15 | %-------------parameters---------------- 16 | % dimension of measurement matrix, measurement rate delta 17 | delta=M/N; 18 | % iterative times 19 | iter=50; 20 | % initial x_hat and z_hat 21 | x_hat=zeros(N,1); 22 | z_hat=y; 23 | z_hatpri=zeros(M,1); 24 | x_p=zeros(N,1); 25 | % parameter to .. 26 | epsilon=1e-6; 27 | % noise level, in the case of noiseless 28 | %sigma=0; 29 | %-----------iterative algorithm------------------ 30 | for ii=1:iter 31 | % noise variance of z_hat 32 | v=(norm(z_hat)^2-M*sigma^2)/N; 33 | % LE step of OAMP 34 | ztmp=zeros(N,1); 35 | ztmp(index)=z_hat; 36 | r_hat=x_hat+1/sqrt(delta)*dct((p.*idct(ztmp))); 37 | %r_hat=x_hat+A'*z_hat 38 | % estimated noise of LE 39 | c=(1/delta)*v+N/M*sigma^2; 40 | %c=v; 41 | % Kernel function to promote sparsity 42 | if K==3 43 | [F,F_div]=Kernel_lin_1(r_hat,c); 44 | elseif K==2 45 | [F,F_div]=Kernel_lin_3(r_hat,c); 46 | elseif K==1 47 | %--BM3D denoiser used in original image denoise-- 48 | [F,F_div]=BM3D_denoiser(r_hat,sqrt(c)); 49 | end 50 | F_kernel=zeros(K,N); 51 | for jj=1:K 52 | F_kernel(jj,:)=F(jj,:)-F_div(jj)*reshape(r_hat,1,N); 53 | end 54 | %---estimate of x by sure minimization---- 55 | C_ff=F_kernel*F_kernel'/N+epsilon*eye(K); 56 | C_fy=conj(F_kernel)*r_hat/N; 57 | C_cal=mldivide(C_ff,C_fy); 58 | % estimated signal 59 | x_hat=F_kernel.'*C_cal; 60 | %--------residual of estimated signal------ 61 | xtmp=1/sqrt(delta)*dct((p.*idct(x_hat))); 62 | z_hat=y-xtmp(index); 63 | z_hatpri=z_hat; 64 | 65 | x_p=x_hat; 66 | errx_out(ii) = errx(x_hat); 67 | end 68 | % it 69 | %-----------sure let output step---------- 70 | P_ff=F*F'/N; 71 | P_ff=P_ff+epsilon*eye(K); 72 | P_fx=1/N*F*r_hat-c*F_div'; 73 | a=mldivide(P_ff,P_fx); 74 | x_hat=F'*a; 75 | %-------------------- 76 | end -------------------------------------------------------------------------------- /TruboCS/test.m: -------------------------------------------------------------------------------- 1 | % -------------------------- 2 | clear; 3 | clc; 4 | %-------------------------- 5 | rou=0.1; 6 | N=3000; 7 | delta=0.5; 8 | M=delta*N; 9 | M=fix(M); 10 | sigma=sqrt(10^(-50/10)); 11 | % sigma=0; 12 | %=========distribution of x========= 13 | pattern=random('Binomial',1,rou,N,1); 14 | x = 1/sqrt(rou)*randn(N,1); 15 | x = x.* pattern; 16 | x = x/norm(x)*sqrt(N); 17 | permuation=randperm(N); 18 | index_selection=permuation(1:M); 19 | p=2*(rand(N,1)>0.5)-1; 20 | % p2=2*(rand(N,1)>0.5)-1; 21 | % xtmp=1/sqrt(delta)*dct((p.*idct(x))); % xtmp= F*x; 22 | xtmp = 1/sqrt(delta)*dct((p.*idct(x))); 23 | y=xtmp(index_selection)+sigma*randn(M,1); %y = S*xtmp + w (S*F = AS) 24 | 25 | iter=30; 26 | K=3; 27 | epsilon=1e-6; 28 | errx = @(z) norm(z-x)^2/norm(x); 29 | [errx_out,x_hat] = dturbocs(y,p,M,N,K,index_selection,sigma,errx); 30 | semilogy(errx_out) 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | % W.J.Yan, 3.2019 2 | 3 | clc; 4 | clear; 5 | tic 6 | % randn('state',1); 7 | % rand('state',1); 8 | % randi('state',1); 9 | setup_DL 10 | 11 | N_Rec = [32]; % receiver antenna 12 | N_IRS = [16]; % IRS antenna 13 | N_L = 100; % coherencr time 14 | SNR = [-20 : 1 : -10]; 15 | SimLen = 5000; % average simulation time 16 | 17 | rho = 0.9 ; % mean_s 18 | nit.outer = 200 ; % limit iterations for SIMO_Z_MessPass 19 | nit.inners = 10; % limit iterations for SIMO_S_MessPass 20 | nit.innerx = 3 ; 21 | QAM = 4; % modulate style, only for: 4 : QPSK; 16 : 16QAM. 22 | 23 | 24 | for iR = 1 : length(N_Rec) 25 | for iS = 1 : length(N_IRS) 26 | 27 | optIn.M = N_Rec(iR); 28 | optIn.N = N_IRS(iS); 29 | optIn.L = N_L; 30 | optIn.QAM = QAM; 31 | optIn.rho = rho; 32 | optIn.nit = nit; %limit iterations 33 | 34 | X_BER = zeros(1, length(SNR)); % average of bit error rate of X 35 | S_BER = zeros(1, length(SNR)); % average of bit error rate of S 36 | for sim = 1 : SimLen 37 | 38 | tX_BER = zeros(1, length(SNR)); % bit error rate of X in each iteration 39 | tS_BER = zeros(1, length(SNR)); % bit error rate of S in each iteration 40 | %% 41 | for iN = 1 : length(SNR) 42 | 43 | optIn.SNR = SNR(iN); 44 | 45 | results = SIMO_algorithm(optIn); % subfunction 46 | 47 | tX_BER(iN) = results.Xerr; 48 | tS_BER(iN) = results.Serr; 49 | 50 | end 51 | %% 52 | X_BER = X_BER*(sim-1)/sim + tX_BER/sim; 53 | S_BER = S_BER*(sim-1)/sim + tS_BER/sim; 54 | sim 55 | % fprintf('sim = %3d, M = %3d, N = %3d, L = %3d, QAM = %2d, rho = %2d\n', sim, optIn.M, optIn.N, optIn.L, optIn.QAM, rho ); 56 | % 57 | % fprintf('SNR ='); 58 | % for iN = 1:length(SNR) 59 | % fprintf('%2d ', SNR(iN)); 60 | % end 61 | % fprintf('\n'); 62 | % 63 | % fprintf('tX_BER ='); 64 | % for iN = 1:length(SNR) 65 | % fprintf('%3.6e ', tX_BER(iN)); 66 | % end 67 | % fprintf('\n'); 68 | % 69 | % fprintf('X_BER ='); 70 | % for iN = 1:length(SNR) 71 | % fprintf('%3.6e ', X_BER(iN)); 72 | % end 73 | % fprintf('\n'); 74 | % 75 | % fprintf('tS_BER ='); 76 | % for iN = 1:length(SNR) 77 | % fprintf('%3.6e ', tS_BER(iN)); 78 | % end 79 | % fprintf('\n'); 80 | % 81 | % fprintf('S_BER ='); 82 | % for iN = 1:length(SNR) 83 | % fprintf('%3.6e ', S_BER(iN)); 84 | % end 85 | % fprintf('\n'); 86 | 87 | end 88 | 89 | fid = fopen('SIMO_result.txt','a+'); 90 | fprintf(fid,'\n'); 91 | fprintf(fid,'SimLen = %3d, M = %3d, N = %3d, L = %3d, QAM = %2d\n', sim, optIn.M, optIn.N, optIn.L, optIn.QAM ); 92 | fprintf(fid, 'SNR ='); 93 | for iN = 1:length(SNR) 94 | fprintf(fid, '%2d ', SNR(iN)); 95 | end 96 | fprintf(fid, '\n'); 97 | 98 | fprintf(fid, 'X_BER ='); 99 | for iN = 1:length(SNR) 100 | fprintf(fid, '%3.6e ', X_BER(iN)); 101 | end 102 | fprintf(fid, '\n'); 103 | 104 | fprintf(fid, 'S_BER ='); 105 | for iN = 1:length(SNR) 106 | fprintf(fid, '%3.6e ', S_BER(iN)); 107 | end 108 | fprintf(fid, '\n'); 109 | end 110 | end 111 | save 112 | toc 113 | %% 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /matlab.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yuan-Xiaojun/Matlab_SIMO/81b4b867934770a589afc41857c1288b5181bfd5/matlab.mat -------------------------------------------------------------------------------- /setup_DL.m: -------------------------------------------------------------------------------- 1 | %Add Paths for DL experiments 2 | 3 | %NOTE: some of the comparison codes require MEX files to be built. Compiled 4 | %mex code for 64-bit MATLAB running on MAC OS X are included. These files 5 | %will need to be built for other platforms 6 | 7 | 8 | %Get absolute path to the folder containing this file 9 | basePath = [fileparts(mfilename('fullpath')) filesep]; 10 | 11 | addpath([basePath '/BiGAMP']) %BiG-AMP code 12 | addpath([basePath '/TruboCS']) %TruboCS code 13 | 14 | 15 | 16 | --------------------------------------------------------------------------------