Parity check matrix of LDPC encoder and decoder in Matlab - matlab

MATLAB provides powerful LDPC encoder and decoder objects in the latest versions. However the parity check matrix H, with dimension (N-K) by N, needs to satisfy the following condition:
"The last N−K columns in the parity check matrix H must be an invertible matrix in GF(2)"
Indeed, this condition is not easy to be satisfied for most LDPC codes, although we know that there is at least one (N-M) by (N-M) invertible sub-block in the parity check matrix H, if H is with a full rank.
I want to know that, if there exists a fast algorithm or a MATLAB function, which can find out an invertible sub-block in H provided H is with a full rank. So that we can use the MATLAB objects and Simulink blocks conveniently.

I tried repermuting the columns of H matrix until it matches the Malab
% Programmer: Taha Valizadeh
% Date: September 2016
%% Column Permutation
% Permute columns of a binary Matrix until the rightmost square matrix is
% invertible over GF(2)
% matrix dimensions:
[~, n] = size(H);
% Initialization
HInvertible = H;
PermutorIndex = 1:n;
flag = true;
counter = 0;
% Initial Report
disp('Creating a ParityCheck matrix which is suitable for MATLAB COMM Tollbox')
% Permute columns
while flag
% Check if the rightmost square matrix is invertible over GF(2)
try
EncoderObject = comm.LDPCEncoder(sparse(HInvertible));
% Check if new matrix works
fprintf(['ParityCheck Matrix become suitable for Matlab LDPC Encoder ',...
'after ',num2str(counter),' permutations!\n'])
flag = false; % Break the loop
catch
% Choose different columns for the rightmost part of matrix
counter = counter+1; %Permutation Counter
PermutorIndex = randperm(n);
HInvertible = H(:,PermutorIndex);
end
end

Related

When and how to do zero-padding for a discrete convolution?

I want to take the discrete convolution of two 1-D vectors. The vectors correspond to intensity data as a function of frequency. My goal is to take the convolution of one intensity vector B with itself and then take the convolution of the result with the original vector B, and so on, each time taking the convolution of the result with the original vector B. I want the final result to have the same length as the original vector B.
I am starting with a code in IDL that I am trying to modify to MATLAB. The relevant part of the code reads:
for i=1,10 do begin
if i lt 2 then A=B else A=Rt
n=i+1
Rt=convol(A,B,s,center=0,/edge_zero)
...
endfor
which I have rewritten in MATLAB
for i = 2:11
if i < 3
A = B; % indices start at 0, not 1
else
A = Rt;
end
n = i + 1;
% Scale by 1/s
Rt = (1/s).*conv(A,B);
...
end
But I am not sure how to incorporate the zero-padding that uses the edge_zero option. In IDL, the convolution calculates the values of elements at the edge of the vector as if the vector were padded with zeroes. The optional third option for the convolution function in MATLAB includes the option 'same', which returns the central part of the convolution of the same size as u for conv(u,v), but that doesn't seem to be the correct way about this problem. How do I do an analogous zero-padding in MATLAB?
Here is a code I needed for my doctoral research that I know does the zero padding correctly. I hope it helps.
function conv_out=F_convolve_FFT(f,g,dw,flipFlag),
if(nargin<4), flipFlag==0; end;
% length of function f to be convolved, initialization of conv_out, and padding p
N=length(f); conv_out=zeros(1,N); p=zeros(1,N);
% uncomment if working with tensor f,g's of rank 3 or greater
% f=F_reduce_rank(f); g=F_reduce_rank(g);
% padding. also, this was commented out: EN=length(fp);
fp = [f p]; gp = [g p];
% if performing convolution of the form c(w) = int(f(wp)g(w+wp),wp) = int(f(w-wp)gbar(wp),wp) due to reverse-order domain on substitution
if(flipFlag==1), gp=fliplr(gp); end;
% perform the convolution. You do NOT need to multiply the invocation of "F_convolve_FFT(f,g,dw,flipFlag)" in your program by "dx", the finite-element.
c1 = ifft(fft(fp).*fft(gp))*dw;
% if performing "reverse" convolution, an additional circshift is necessary to offset the padding
if(flipFlag==1), c1=circshift(c1',N)'; end;
% offset the padding by dNm
if(mod(N,2)==0), dNm=N/2; elseif(mod(N,2)==1), dNm=(N-1)/2; end;
% padding. also, this was commented out: EN=length(fp);
conv_out(:)=c1(dNm+1:dNm+N);
return

Transform random draws from a bivariate normal into the unit square in Matlab

I have an nx2 matrix r in Matlab reporting n draws from a bivariate normal distribution
n=1000;
m1=0.3;
m2=-m1;
v1=0.2;
n=10000;
v2=2;
rho=0.5;
mu = [m1, m2];
sigma = [v1,rho*sqrt(v1)*sqrt(v2);rho*sqrt(v1)*sqrt(v2),v2];
r = mvnrnd(mu,sigma,n);
I want to normalise these draws to the unit square [0,1]^2
First option
rmax1=max(r(:,1));
rmin1=min(r(:,1));
rmax2=max(r(:,2));
rmin2=min(r(:,2));
rnew=zeros(n,2);
for i=1:n
rnew(i,1)=(r(i,1)-rmin1)/(rmax1-rmin1);
rnew(i,2)=(r(i,2)-rmin2)/(rmax2-rmin2);
end
Second option
rmin1, rmax1, rmin2, rmax2 may be quite variable due to the sampling process. An alternative is applying the 68–95–99.7 rule (here) and I am asking for some help on how to generalise it to a bivariate normal (in particular Step 1 below). Here's my idea
%Step 1: transform the draws in r into draws from a bivariate normal
%with variance-covariance matrix equal to the 2x2 identity matrix
%and mean equal to mu
%How?
%Let t be the transformed vector
%Step 2: apply the 68–95–99.7 rule to each column of t
tmax1=mu(1)+3*1;
tmin1=mu(1)-3*1;
tmax2=mu(2)+3*1;
tmin2=mu(2)-3*1;
tnew=zeros(n,2);
for i=1:n
tnew(i,1)=(t(i,1)-tmin1)/(tmax1-tmin1);
tnew(i,2)=(t(i,1)-tmin2)/(tmax2-tmin2);
end
%Step 3: discard potential values (very few) outside [0,1]
In your case the x and y coordinates of the random vector are correlated, so it's not just a transformation in x and in y independently. You first need to rotate your samples so that x and y become uncorrelated (then the covariance matrix will be diagonal. You don't need it to be the identity, since anywya you normalize later). Then you can apply the transformation you call "2nd option" to the new x and y independently. Shortly, you need to diagonalize the covariance matrix.
As a side note, your code adds/subtracts 3 times 1, instead of 3 times the standard deviation. Also, you can avoid the for loop, using (e.g) Matlab's bsxfun which applies an operation between matrix and vector:
t = bsxfun(#minus,r,mean(r,1)); % center the data
[v, d] = eig(sigma); % find the directions for projection
t = t * v; % the projected data is uncorrelated
sigma_new = sqrt(diag(d)); % that's the std in the new coordinates
% now transform each coordinate independently
tmax1 = 3*sigma_new(1);
tmin1 = -3*sigma_new(1);
tmax2 = 3*sigma_new(2);
tmin2 = -3*sigma_new(2);
tnew = bsxfun(#minus, t, [tmin1, tmin2]);
tnew = bsxfun(#rdivide, tnew, [tmax1-tmin1, tmax2-tmin2]);
You still need to discard the few samples which are out of [0,1], as you wrote.

Understanding PCA in MATLAB

What are the difference between the following two functions?
prepTransform.m
function [mu trmx] = prepTransform(tvec, comp_count)
% Computes transformation matrix to PCA space
% tvec - training set (one row represents one sample)
% comp_count - count of principal components in the final space
% mu - mean value of the training set
% trmx - transformation matrix to comp_count-dimensional PCA space
% this is memory-hungry version
% commented out is the version proper for Win32 environment
tic;
mu = mean(tvec);
cmx = cov(tvec);
%cmx = zeros(size(tvec,2));
%f1 = zeros(size(tvec,1), 1);
%f2 = zeros(size(tvec,1), 1);
%for i=1:size(tvec,2)
% f1(:,1) = tvec(:,i) - repmat(mu(i), size(tvec,1), 1);
% cmx(i, i) = f1' * f1;
% for j=i+1:size(tvec,2)
% f2(:,1) = tvec(:,j) - repmat(mu(j), size(tvec,1), 1);
% cmx(i, j) = f1' * f2;
% cmx(j, i) = cmx(i, j);
% end
%end
%cmx = cmx / (size(tvec,1)-1);
toc
[evec eval] = eig(cmx);
eval = sum(eval);
[eval evid] = sort(eval, 'descend');
evec = evec(:, evid(1:size(eval,2)));
% save 'nist_mu.mat' mu
% save 'nist_cov.mat' evec
trmx = evec(:, 1:comp_count);
pcaTransform.m
function [pcaSet] = pcaTransform(tvec, mu, trmx)
% tvec - matrix containing vectors to be transformed
% mu - mean value of the training set
% trmx - pca transformation matrix
% pcaSet - output set transforrmed to PCA space
pcaSet = tvec - repmat(mu, size(tvec,1), 1);
%pcaSet = zeros(size(tvec));
%for i=1:size(tvec,1)
% pcaSet(i,:) = tvec(i,:) - mu;
%end
pcaSet = pcaSet * trmx;
Which one is actually doing PCA?
If one is doing PCA, what is the other one doing?
The first function prepTransform is actually doing the PCA on your training data where you are determining the new axes to represent your data onto a lower dimensional space. What it does is that it finds the eigenvectors of the covariance matrix of your data and then orders the eigenvectors such that the eigenvector with the largest eigenvalue appears in the first column of the eigenvector matrix evec and the eigenvector with the smallest eigenvalue appears in the last column. What's important with this function is that you can define how many dimensions you want to reduce the data down to by keeping the first N columns of evec which will allow you to reduce your data down to N dimensions. The discarding of the other columns and keeping only the first N is what is set as trmx in the code. The variable N is defined by the prep_count variable in prepTransform function.
The second function pcaTransform finally transforms data that is defined within the same domain as your training data but not necessarily the training data itself (it could be if you wish) onto the lower dimensional space that is defined by the eigenvectors of the covariance matrix. To finally perform the reduction of dimensions, or dimensionality reduction as it is popularly known, you simply take your training data where each feature is subtracted from its mean and you multiply your training data by the matrix trmx. Note that prepTransform outputting the mean of each feature in the vector mu is important in order to mean subtract your data when you finally call pcaTransform.
How to use these functions
To use these functions effectively, first determine the trmx matrix, which contain the principal components of your data by first defining how many dimensions you want to reduce your data down to as well as the mean of each feature stored in mu:
N = 2; % Reduce down to two dimensions for example
[mu, trmx] = prepTransform(tvec, N);
Next you can finally perform dimensionality reduction on your data that is defined within the same domain as tvec (or even tvec if you wish, but it doesn't have to be) by:
pcaSet = pcaTransform(tvec, mu, trmx);
In terms of vocabulary, pcaSet contain what are known as the principal scores of your data, which is the term used for the transformation of your data to the lower dimensional space.
If I can recommend something...
Finding PCA through the eigenvector approach is known to be unstable. I highly recommend you use the Singular Value Decomposition via svd on the covariance matrix where the V matrix of the result already gives you the eigenvectors sorted which correspond to your principal components:
mu = mean(tvec, 1);
[~,~,V] = svd(cov(tvec));
Then perform the transformation by taking the mean subtracted data per feature and multiplying by the V matrix, once you subset and grab the first N columns of V:
N = 2;
X = bsxfun(#minus, tvec, mu);
pcaSet = X*V(:, 1:N);
X is the mean subtracted data which performs the same thing as doing pcaSet = tvec - repmat(mu, size(tvec,1), 1);, but you are not explicitly replicating the mean vector over each training example but letting bsxfun do that for you internally. However, taking advantage of MATLAB R2016b, this repeating can be done without the explicit call to bsxfun:
X = tvec - mu;
Further Reading
If you fully want to understand the code that was written and the theory behind what it's doing, I recommend the following two Stack Overflow posts that I have written that talk about the topic:
What does selecting the largest eigenvalues and eigenvectors in the covariance matrix mean in data analysis?
How to use eigenvectors obtained through PCA to reproject my data?
The first post brings the code you presented into light which performs PCA using the eigenvector approach. The second post touches base on how you'd do it using the SVD towards the end of the answer. This answer I've written here is a mix between the two posts above.

select optimal column vector from a matrix subject to a localised goal vector constraint

How to automatically select the column vector of a matrix within which the scalar values in a subset of elements is closest to those in a predefined goal vector of the same sub set?
I solved the problem and tested method on 100,10 matrix, it works - should also work for larger matrices, while hopefully not becoming too computationally expensive
%% Selection of optimal source function
% Now need to select the best source function in the data matrix
% k = 1,2,...n within which scalar values of a random set of elements are
% closest to a pre-defined goal vector with the same random set
% Proposed Method:
% Project the columns of the data matrix onto the goal vector
% Calculate the projection error vector matrix; the null space of the
% local goal vector, is orthogonal to its row space
% The column holding the minimum error vector is the optimal column
% [1] find the null space of the goal vector, containing the projection
% errors
mpg = pinv(gloc);
xstar = mpg*A;
p = gloc*xstar;
nA = A-p;
% [2] the minimum error vector will correspond to the optimal source
% function
normnA = zeros(1,n);
for i = 1:n
normnA(i) = norm(nA(:,i));
end
minnA = min(normnA);
[row,k] = find(normnA == minnA);
disp('The optimal source function is: ')
disp(k)

Matlab vectorizing equations and matrix multiplication

I have a program that currently uses a for loop to iterate through a set of functions. I've tried using parfor but that only works on the university's version of Matlab. I'd like to vectorize the handling of this so that a for loop isn't necessary. The equations I'm using basically call different types of Bessel functions and are contained in separate functions.
Here's what I'm trying to do:
For each value of m, build a vector of matrix elements for each required matrix. Then build each full matrix. I think this is working correctly.
Where it's throwing an error is on the final matrix multiplication... even if I just multiply the left 2x2 by the middle 2x2 I get the dreaded error:
??? Error using ==> mtimes
Inner matrix dimensions must agree.
Error in ==> #(m)CL(m)*CM(m)*CR(m)
% Vector for summation. 1 row, 301 columns with data from 0->300
m_max=301;
m=[0:m_max-1];
% Build the 300 elements for the left 2x2 matrix.
CL_11=#(m) H1(m,alpha1);
CL_12=#(m) H2(m,alpha1);
CL_21=#(m) n1*dH1(m,alpha1);
CL_22=#(m) n1*dH2(m,alpha1);
% Build the 300 elements for the middle 2x2 matrix.
CM_11=#(m) n1*dH2(m,alpha2);
CM_12=#(m) -1*H2(m,alpha2);
CM_21=#(m) -1*n1*dH1(m,alpha2);
CM_22=#(m) H1(m,alpha2);
% Build the 300 elements for the right 2x1 matrix.
CR_11=#(m) J(m,alpha3);
CR_21=#(m) n2*dJ(m,alpha3);
% Build the left (CL), middle (CM) and right (CR) matrices.
CL=#(m) [CL_11(m) CL_12(m);CL_21(m) CL_22(m)];
CM=#(m) [CM_11(m) CM_12(m);CM_21(m) CM_22(m)];
CR=#(m) [CR_11(m);CR_21(m)];
% Build the vector containing the products of each triplet of
% matrices.
C=#(m) CL(m)*CM(m)*CR(m);
cl=CL(m)
cm=CM(m)
cr=CR(m)
c=CL(m)*CM(m)*CR(m)
If you have any suggestions or recommendations, I'd greatly appreciate it! I'm still a newbie with Matlab and am trying to develop a higher level of ability with use of matrices and vectors.
Thanks!!
Your matrices are not 2x2. When you do CL_11(m) with m a 1x300 vector, CL_11(m) will be 1x300 as well. Thus CL(m) is 2x301. To get around this, you have to calculate the matrices one-by-one. There are two approaches here.
c=arrayfun(C,m,'UniformOutput',false)
will return a cell array, and so c{1} corresponds to m(1), c{2} to m(2), etc.
On the other hand, you can do
for i=1:m_max
c(:,:,i)=C(m(i));
end
and then c(:,:,i) corresponds to m(1), etc.
I'm not sure which version will be faster, but you can test it easily enough with your code.
If you go through the symbolic toolbox you can construct a function that is easier to handle.
%% symbolic
CL = sym('CL',[2,2])
CM = sym('CM',[2,2])
CR = sym('CR',[2,1])
r = CL*CM*CR
f = matlabFunction(r)
%% use some simple functions so it can be calculated as example
CL_11=#(m) m+1;
CL_12=#(m) m;
CL_21=#(m) m-1;
CL_22=#(m) m+2;
CM_11=#(m) m;
CM_12=#(m) m;
CM_21=#(m) 2*m;
CM_22=#(m) 2*m;
CR_11=#(m) m;
CR_21=#(m) 1-m;
%% here the substitution happens:
fh = #(m) f(CL_11(m),CL_12(m),CL_21(m),CL_22(m),CM_11(m),CM_12(m),CM_21(m),CM_22(m),CR_11(m),CR_21(m))
Out of interest I did a small speed test:
N=1e5;
v = 1:N;
tic
% .... insert symbolic stuff from above
r1 = fh(v);
t1=toc % gives 0.0842s for me
vs
CL=#(m) [CL_11(m) CL_12(m);CL_21(m) CL_22(m)];
CM=#(m) [CM_11(m) CM_12(m);CM_21(m) CM_22(m)];
CR=#(m) [CR_11(m);CR_21(m)];
C=#(m) CL(m)*CM(m)*CR(m);
tic
r2 =arrayfun(C,v,'UniformOutput',false);
t2=toc % gives 7.6874s for me
and
tic
r3 = nan(2,N);
for i=1:N
r3(:,i)=C(v(i));
end
t3=toc % 8.1503s for me