Gauss-Jordan elimination over GF(2) - matlab

I need to transform a parity-check matrix H (that only consists of ones and zeros) from a non-standard to a standard form, this is, express it as:
Hsys = [A | I]
H and Hsys share the same dimension: (n-k,n). I above corresponds to an identity matrix of dimension (n-k).
Gauss-Jordan elimination comes in handy to solve this problem. Matlab has an specific command, rref, for this purpose, however it is no longer valid while working over GF(2) as in our case. Glancing through the Internet I found in Github a potentially suitable solution to overcome this drawback. However it does not always work out.
I also tried doing HH = mod(rref(H),2), which did not work at all, as many of the output elements weren't binary.
Here below you may find three samples of non-standard parity check matrices in which Gauss-Jordan elimination (over GF(2)) can be applied. As there should always be a way to arrange any matrix to be systematic, I would need a method that works out with matrices of any dimension.
These first sample is taken from sid's post in Stackoverflow, not responded yet:
H=[1 0 1 1 0;
0 0 1 0 1;
1 0 0 1 0;
1 0 1 1 1];
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
The last one is a matrix of dimension (50x100) and can be found in this link to my Dropbox.
Edit on 21/06/2017
The solution proposed by #Jonas worked out in some cases, but not in most of them, as H matrix seems to be singular. Any other similar way to do this?
Thank you in advance, and best regards.

Here is how I'd do it (using Gauss-Jordan elimination):
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
rows = size(H, 1);
cols = size(H, 2);
r = 1;
for c = cols - rows + 1:cols
if H(r,c) == 0
% Swap needed
for r2 = r + 1:rows
if H(r2,c) ~= 0
tmp = H(r, :);
H(r, :) = H(r2, :);
H(r2, :) = tmp;
end
end
% Ups...
if H(r,c) == 0
error('H is singular');
end
end
% Forward substitute
for r2 = r + 1:rows
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Back Substitution
for r2 = 1:r - 1
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Next row
r = r + 1;
end
Let me know if this doesn't solve your issue.

I went through the same issue and #jonas code also produced mostly singular matrix error. you can try the following code which I found to be helpful when searching for the systematic form of H. Its also include the calculation of G.
% Gauss-Jordan elimination
swaps=zeros(m,2);
swaps_count=1;
n=size(H, 2);
m=size(H, 1);
j=1;
index=1;
while index<=m
i=index;
while (HH(i,j)==0)&(i<m)
i=i+1;
end
if HH(i,j)==1
temp=HH(i,:);
HH(i,:)=HH(index,:);
HH(index,:)=temp;
for i=1:m
if (index~=i)&(HH(i,j)==1)
HH(i,:)=mod(HH(i,:)+HH(index,:),2);
end
end
swaps(swaps_count,:)=[index j];
swaps_count=swaps_count+1;
index=index+1;
j=index;
else
j=j+1;
end
end
for i=1:swaps_count-1
temp=HH(:,swaps(i,1));
HH(:,swaps(i,1))=HH(:,swaps(i,2));
HH(:,swaps(i,2))=temp;
end
G=[(HH(:,m+1:n))' eye(n-m)];
for i=swaps_count-1:-1:1
temp=G(:,swaps(i,1));
G(:,swaps(i,1))=G(:,swaps(i,2));
G(:,swaps(i,2))=temp;
end
disp(sum(sum((mod(H*G',2)))));

Related

Replace repeated value based on sequence size - Matlab

I have a 2D matrix composed of ones and zeros.
mat = [0 0 0 0 1 1 1 0 0
1 1 1 1 1 0 0 1 0
0 0 1 0 1 1 0 0 1];
I need to find all consecutive repetitions of ones in each row and replace all ones with zeros only when the sequence size is smaller than 5 (5 consecutive ones):
mat = [0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0];
Any suggestion on how to approach this problem would be very welcome.
You can use diff to find the start and end points of the runs of 1, and some logic based on that to zero out the runs which are too short. Please see the below code with associated comments
% Input matrix of 0s and 1s
mat = [0 0 0 0 1 1 1 0 0
1 1 1 1 1 0 0 1 0
0 0 1 0 1 1 0 0 1];
% Minimum run length of 1s to keep
N = 5;
% Get the start and end points of the runs of 1. Add in values from the
% original matrix to ensure that start and end points are always paired
d = [mat(:,1),diff(mat,1,2),-mat(:,end)];
% Find those start and end points. Use the transpose during the find to
% flip rows/cols and search row-wise relative to input matrix.
[cs,r] = find(d.'>0.5); % Start points
[ce,~] = find(d.'<-0.5); % End points
c = [cs, ce]; % Column number array for start/end
idx = diff(c,1,2) < N; % From column number, check run length vs N
% Loop over the runs which didn't satisfy the threshold and zero them
for ii = find(idx.')
mat(r(ii),c(ii,1):c(ii,2)-1) = 0;
end
If you want to throw legibility out of the window, this can be condensed for a slightly faster and denser version, based on the exact same logic:
[c,r] = find([mat(:,1),diff(mat,1,2),-mat(:,end)].'); % find run start/end points
for ii = 1:2:numel(c) % Loop over runs
if c(ii+1)-c(ii) < N % Check if run exceeds threshold length
mat(r(ii),c(ii):c(ii+1)-1) = 0; % Zero the run if not
end
end
The vectorized solution by #Wolfie is nice and concise, but a bit hard to understand and far from the wording of the problem. Here is a direct translation of the problem using loops. It has the advantage of being easier to understand and is slightly faster with less memory allocations, which means it will work for huge inputs.
[m,n] = size(mat);
for i = 1:m
j = 1;
while j <= n
seqSum = 1;
if mat(i,j) == 1
for k = j+1:n
if mat(i,k) == 1
seqSum = seqSum + 1;
else
break
end
end
if seqSum < 5
mat(i,j:j+seqSum-1) = 0;
end
end
j = j + seqSum;
end
end

Filling up gaps in matrix's rows

Let g be a matrix containing ones\zeroes. I want to fill up gaps of zeros (complete ones sequences) in the rows of g which are smaller then a given k.
For example fill up with ones all gaps smaller then three zeros. This code will work:
[m,n]=size(g);
k=3
for i=1:m
j=1
while (j<n)
if(g(i,j)==0)
flag=0;
for w=1:k
if(g(i,j+w-1)==1)
flag=1;
end
end
if(flag)
for w=1:k
g(i,j+w-1)=1;
end
else
while(~flag&j<n)
j=j+1;
if(g(i,j)==1)
flag=1;
end
end
end
end
j=j+1;
end
end
Is there a way to do so without all the for loops?
A short version using some built-in function:
M = [1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1]
Mopen = ~imopen(~padarray(M,[0,1],1),strel('line',3,0));
Mfill = Mopen(:,2:end-1);
A vectorized version:
k = 3;
d = diff( g,1,2);
L = d ~= 0;
c = cumsum([zeros(size(g,1),1) L],2)+1;
b = bsxfun(#plus, c, cumsum([0; c(1:end-1,end)]));
a =accumarray(reshape(b.',[],1),1);
f= find(a<k);
g(ismember(b,f) & g==0) = 1;
Example :
g =
1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1
result =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 0 0 0
1 1 1 1 1
Another potential solution is to cast each row to a char array and then perform substitutions based on a regular expressions
g = round(rand(30,70));
figure();
subplot(121);
imagesc(g)
[m,n]=size(g);
k=3;
pattern = ['(?<!',char(0),')(',char(0),'{1,',num2str(k-1),'})(?!',char(0),')'];
for i=1:m
[matchstart,matchend] = regexp(char(g(i,:)),pattern);
for j = 1:length(matchstart)
g(i,matchstart(j):matchend(j)) = 1;
end
end
subplot(122);
imagesc(g)

How to make a parity check matrix from non-systematic to systematic in Matlab? thanks

I am trying to make a parity check matrix from non-systematic to systematic. Hence, I am attaching my code below. Somewhat it is correct, but there are some problems. It would be really great if someone could help me in this.
Subject: Information theory and coding. I am working on LDPC coding and decoding. Please check the code below
MATLAB CODE:
H = [1 0 1 1 0; 0 0 1 0 1; 1 0 0 1 0; 1 0 1 1 1]
[m,n] = size(H);
k = n-m;
for i = k+1:n
%H(:,i)
ind = find(H(:,i),1,'last');
% exchanging (ind)th row and (i-k)th row
if ind < i-k
continue;
end
if ind ~= i-k
temp = H(ind,:);
H(ind,:) = H(i-k,:);
H(i-k,:) = temp;
end
I = find(H(:,i));
% Guassian elimination
for j = 1:length(I)
if I(j) ~= i-k
H(I(j),:) = mod(H(I(j),:)+H(i-k,:),2);
end
end
end
Hsys = H
For e.g.
This is my H matrix:
H =
1 0 1 1 0
0 0 1 0 1
1 0 0 1 0
1 0 1 1 1
I want to have an identity matrix inside the matrix. The dimension on H matrix here is (mxn) which is (4x5).
Generally we use Gaussian elimination method to make the Identity matrix.hence, we make operations between rows. This is how we make it systematic.
I should have matrix as this in the result:
Hsys =
0 1 0 0 0
0 0 1 0 0
1 0 0 1 0
0 0 0 0 1
I should have an identity matrix of dimension m.
Here is how I'd do it (using Gauss-Jordan elimination):
% Not your matrix since it does not have any ones in the second column.
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
rows = size(H, 1);
cols = size(H, 2);
r = 1;
for c = cols - rows + 1:cols
if H(r,c) == 0
% Swap needed
for r2 = r + 1:rows
if H(r2,c) ~= 0
tmp = H(r, :);
H(r, :) = H(r2, :);
H(r2, :) = tmp;
end
end
end
% Ups...
if H(r,c) == 0
error('H is singular');
end
% Forward substitute
for r2 = r + 1:rows
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Back Substitution
for r2 = 1:r - 1
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Next row
r = r + 1;
end

How to count the number of 1's from the total matrix

I have code like below:
N=10;
R=[1 1 1 1 1 0 0 0 0 0;1 1 1 1 1 1 1 1 1 1];
p=[0.1,0.2,0.01];
B = zeros(N , N);
B(1:N,1:N) = eye(N);
C=[B;R];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
end
from this code I vary the value of p. So for different value of p, i am getting different Rp. Now I want to get the total number of "1"'s from each Rp matrix. it means may be for p1 I am getting Rp1=5, for p2, Rp=4.
For example
Rp1=[1 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
Rp2=[1 0 0 0 0;0 1 0 0 0;1 0 0 0 0],
Rp3=[0 0 0 0 0;0 1 0 0 0;0 0 0 0 0],
So total result will be 2,3,1.
I want to get this result.
If the matrix contains only 0 and 1 you are trying to count the nonzero values and there is a function for that called nnz
n = nnz(Rp);
As I mentioned in the comments you should replace
if(rand < p)
with
if(rand < q)
Then you can add the number of nonzero values to a vector like
r = [];
for q=p(1:length(p))
Rp=C;
for i=1:N
if(rand < p)
Rp(i,:) = 0;
end
end
r = [r nnz(Rp)];
end
Then r will contain your desired result. There are many ways to improve your code as mentioned in other answers and comments.
Assuming Rp is your matrix, then simply do one of the following:
If your matrix only contains zeros and ones
sum(Rp(:))
Or if your matrix contains multiple values:
sum(Rp(:)==1)
Note that for two dimensional matrices sum(Rp(:)) is the same as sum(sum(Rp))
I think your real question is how to save this result, you can do this by assigning it to an indexed varable, for example:
S(count) = sum(Rp(:));
This will require you to add a count variable that increases with one every step of the loop. It will be good practice (and efficient) to initialize your variable properly before the loop:
S = zeros(length(p),1);
If you need to count the 1's in any matrix M you should be able to do sum(M(:)==1)

MATLAB Expanding A Matrix with Zeros

I need a matrix of nxn, where the first pxp of it contains ones and rest are zeros. I can do it with traversing the cells, so I'm not asking a way to do it. I'm looking for "the MATLAB way" to do it, using built-in functions and avoiding loops etc.
To be more clear;
let n=4 and p=2,
then the expected result is:
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
There are possibly more than one elegant solution to do it, so I will accept the answer with the shortest and most readable one.
P.S. The question title looks a bit irrelevant: I put that title because my initial approach would be creating a pxp matrix with ones, then expanding it to nxn with zeros.
The answer is creating a matrix of zeroes, and then setting part of it to 1 using indexing:
For example:
n = 4;
p = 2;
x = zeros(n,n);
x(1:p,1:p) = 1;
If you insist on expanding, you can use:
padarray( zeros(p,p)+1 , [n-p n-p], 0, 'post')
Another way to expand the matrix with zeros:
>> p = 2; n = 4;
>> M = ones(p,p)
M =
1 1
1 1
>> M(n,n) = 0
M =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
You can create the matrix easily by concatenating horizontally and vertically:
n = 4;
p = 2;
MyMatrix = [ ones(p), zeros(p, n-p); zeros(n-p, n) ];
>> p = 2; n = 4;
>> a = [ones(p, 1); zeros(n - p, 1)]
a =
1
1
0
0
>> A = a * a'
A =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0