Is there any function in MATLAB for changing the form of a matrix? - matlab

I have to get the unknown matrix by changing the form of a known matrix considering the following rules:
H = [-P'|I] %'
G = [I|P]
where
H is a known matrix
G is an unknown matrix which has to be calculated
I is the identity matrix
So for example, if we had a matrix,
H = [1 1 1 1 0 0;
0 0 1 1 0 1;
1 0 0 1 1 0]
its form has to be changed to
H = [1 1 1 1 0 0;
0 1 1 0 1 0;
1 1 0 0 0 1]
So
-P' = [1 1 1;
0 1 0;
1 1 0]
and in case of binary matrices -P = P.
Therefore
G = [1 0 0 1 1 1;
0 1 0 0 1 0;
0 0 1 1 1 0]
I know how to solve it on paper by performing basic row operations but haven't figured out how to solve it using MATLAB yet.
What is the method for solving the given problem?

If the order of columns in -P' doesn't matter, here's one solution using the function ISMEMBER:
>> H = [1 1 1 1 0 0; 0 0 1 1 0 1; 1 0 0 1 1 0]; %# From above
>> pColumns = ~ismember(H',eye(3),'rows') %'# Find indices of columns that
%# are not equal to rows
pColumns = %# of the identity matrix
1
0
1
1
0
0
>> P = -H(:,pColumns)' %'# Find P
P =
-1 0 -1
-1 -1 0
-1 -1 -1
>> G = logical([eye(3) P]) %# Create the binary matrix G
G =
1 0 0 1 0 1
0 1 0 1 1 0
0 0 1 1 1 1
NOTE: This solution will work properly for integer or binary values in H. If H has floating-point values, you will likely run into an issue with floating-point comparisons when using ISMEMBER (see here and here for more discussion of this issue).

Related

Get dynamic rows of matrix based on the ones of another matrix (Matlab)

I am new to Matlab and I need some help.
I want compute Parity Check Matrix and then to encode a codeword using Generator Matrix
My matrix is the following :
1 0 0 0 1 1 1
0 1 0 0 1 1 0
0 0 1 0 1 0 1
0 0 0 1 0 1 1
The codeword is 1 0 1 1.
My code in Matlab is as follow :
printf('Generator Matrix\n');
G = [
1 0 0 0 1 1 1;
0 1 0 0 1 1 0;
0 0 1 0 1 0 1;
0 0 0 1 0 1 1
]
[k,n] = size(G)
P = G(1:k,k+1:n)
PT = P'
printf('Parity Check Matrix\n');
H = cat(2,PT,eye( n-k ))
printf('Encode the following word : \n');
D = [1 0 1 1]
C = xor( G(1,:), G(3,:) , G(4,:) )
My problem is that I want to get dynamically the rows of G Matrix in order to make the xor operation.
Could you help me please ?
Thanks a lot
You only need matrix multiplication modulo 2:
C = mod(D*G, 2);
Alternatively, compute the sum of the rows of G indicated by D, modulo 2:
C = mod(sum(G(D==1,:), 1), 2);

How to permute elements of a vector by another vector to obtain a matrix of permutations

I want to obtain all the possible permutations of one vector elements by another vector elements. For example one vector is A=[0 0 0 0] and another is B=[1 1]. I want to replace the elements of A by B to obtain all the permutations in a matrix like this [1 1 0 0; 1 0 1 0; 1 0 0 1; 0 1 1 0; 0 1 0 1; 0 0 1 1]. The length of real A is big and I should be able to choose the length of B_max and to obtain all the permutations of A with B=[1], [1 1], [1 1 1],..., B_max.
Thanks a lot
Actually, since A and B are always defined, respectively, as a vector of zeros and a vector of ones, this computation is much easier than you may think. The only constraints you should respect concerns B, which shoud not be empty and it's elements cannot be greater than or equal to the number of elements in A... because after that threshold A will become a vector of ones and calculating its permutations will be just a waste of CPU cycles.
Here is the core function of the script, which undertakes the creation of the unique permutations of 0 and 1 given the target vector X:
function p = uperms(X)
n = numel(X);
k = sum(X);
c = nchoosek(1:n,k);
m = size(c,1);
p = zeros(m,n);
p(repmat((1-m:0)',1,k) + m*c) = 1;
end
And here is the full code:
clear();
clc();
% Define the main parameter: the number of elements in A...
A_len = 4;
% Compute the elements of B accordingly...
B_len = A_len - 1;
B_seq = 1:B_len;
% Compute the possible mixtures of A and B...
X = tril(ones(A_len));
X = X(B_seq,:);
% Compute the unique permutations...
p = [];
for i = B_seq
p = [p; uperms(X(i,:).')];
end
Output for A_len = 4:
p =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 1 0 0
1 0 1 0
1 0 0 1
0 1 1 0
0 1 0 1
0 0 1 1
1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1

Finding a binary matrix such that the given hamming weight is constant

Given a square binary matrix. I want to get all possible binary matrices which are at d Hamming distance apart.
Suppose
A=[1 0 1;
0 1 1;
1 1 0].
Then a matrix which is one (d) Hamming distance apart is
[0 0 1;
0 1 1;
1 1 0].
Any help in Matlab base coding?
I am hoping that I got the definition of hamming weight right in the given context. Based on that hope/assumption, this might be what you were after -
combs = dec2base(0:2^9-1,2,9)-'0'; %//'# Find all combinations
combs_3d = reshape(combs',3,3,[]); %//'# Reshape into a 3D array
%// Calculate the hamming weights between A and all combinations.
%// Choose the ones with hamming weights equal to `1`
out = combs_3d(:,:,sum(sum(abs(bsxfun(#minus,A,combs_3d)),2),1)==1)
Thus, each 3D slice of out would give you such a 3 x 3 matrix with 1 hamming weight between them and A.
It looks like you have 9 such matrices -
out(:,:,1) =
0 0 1
0 1 1
1 1 0
out(:,:,2) =
1 0 1
0 1 1
0 1 0
out(:,:,3) =
1 0 1
0 0 1
1 1 0
out(:,:,4) =
1 0 1
0 1 1
1 0 0
out(:,:,5) =
1 0 0
0 1 1
1 1 0
out(:,:,6) =
1 0 1
0 1 0
1 1 0
out(:,:,7) =
1 0 1
0 1 1
1 1 1
out(:,:,8) =
1 1 1
0 1 1
1 1 0
out(:,:,9) =
1 0 1
1 1 1
1 1 0
Edit
For big n, you need to use loops it seems -
n = size(A,1);
nsq = n^2;
A_col = A(:).';
out = zeros(n,n,nsq);
count = 1;
for k1 = 0:2^nsq-1
match1 = dec2bin(k1,nsq)-'0';
if sum(abs(match1-A_col))==1
out(:,:,count) = reshape(match1,n,n);
count = count + 1;
end
end

Putting diagonal in an mxn matrix

I'm trying to construct the 2nd order operator matrix in matlab for an mxn matrix (n-2)xn more precisely.
I looked up diag but it only makes a square matrix. Just wondering for ideas.
Again, to reiterate,
D = diag(-2*ones(1,n-1),0)
will return -2 on the main diagonal but an mxn matrix does not have a main diagonal.
You are looking for spdiags:
>> n = 6; m = n-2;
>> D = full(spdiags(-2*ones(m,1),0,m,n))
D =
-2 0 0 0 0 0
0 -2 0 0 0 0
0 0 -2 0 0 0
0 0 0 -2 0 0
Or just use eye:
D = -2*eye(m,n)
Perhaps you want to combine several diagonals:
>> B = [ones(m,1) -2*ones(m,1) ones(m,1)];
>> D = full(spdiags(B,0:2,n-2,n))
D =
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1

Generating linear combination of a matrix

I want to create a matrix A [4x8] as follows.
The matrix A always has 1 as its diagonal. A11,A22,A33,A44 = 1
This matrix can be considered as two halves with first half being the first 4 columns and the second half being the second 4 columns like something below :
1 -1 -1 -1 1 0 0 1
A = -1 1 -1 0 0 1 0 0
-1 -1 1 0 1 0 0 0
-1 -1 -1 1 1 1 0 0
Each row in the first half can have either two or three -1's:
if it has two -1's then that corresponding row in the second half should have one 1
if any row has three -1's the second half of the matrix should have two 1's.
The overall objective is to have the sum of each row to be 0. I need to generate all possible combinations of a matrix like this.
It will be better if the matrix with new combination be created at each iteration so that after using it I can discard it or else storing all the combinations is very space intensive. Can anybody help me ?
one possible solution I could think of is to generate all possible combinations of row1, row2, row3 and row4 and create a matrix in each iteration. Does that look feasible?
Here's one possible solution. If you ignore the diagonal ones for the moment, you can generate all possible patterns for the other 7 values using the functions KRON, REPMAT, PERMS, UNIQUE, EYE, and ONES:
>> rowPatterns = [kron(eye(3)-1,ones(4,1)) ... %# For 2 out of 3 as -1
repmat(eye(4),3,1); ... %# For 1 out of 4 as 1
repmat([-1 -1 -1],6,1) ... %# For 3 out of 3 as -1
unique(perms([1 1 0 0]),'rows')] %# For 2 out of 4 as 1
rowPatterns =
0 -1 -1 1 0 0 0
0 -1 -1 0 1 0 0
0 -1 -1 0 0 1 0
0 -1 -1 0 0 0 1
-1 0 -1 1 0 0 0
-1 0 -1 0 1 0 0
-1 0 -1 0 0 1 0
-1 0 -1 0 0 0 1
-1 -1 0 1 0 0 0
-1 -1 0 0 1 0 0
-1 -1 0 0 0 1 0
-1 -1 0 0 0 0 1
-1 -1 -1 0 0 1 1
-1 -1 -1 0 1 0 1
-1 -1 -1 0 1 1 0
-1 -1 -1 1 0 0 1
-1 -1 -1 1 0 1 0
-1 -1 -1 1 1 0 0
Note that this is 18 possible patterns for any given row, so your matrix A can have 18^4 = 104,976 possible row patterns (quite a bit). You can generate every possible 4-wise row pattern index by using the functions NDGRID, CAT, and RESHAPE:
[indexSets{1:4}] = ndgrid(1:18);
indexSets = reshape(cat(5,indexSets{:}),[],4);
And indexSets will be a 104,976-by-4 matrix with each row containing one combination of 4 values between 1 and 18, inclusive, to be used as indices into rowPatterns to generate a unique matrix A. Now you can loop over each set of 4-wise row pattern indices and generate the matrix A using the functions TRIL, TRIU, EYE, and ZEROS:
for iPattern = 1:104976
A = rowPatterns(indexSets(iPattern,:),:); %# Get the selected row patterns
A = [tril(A,-1) zeros(4,1)] + ... %# Separate the 7-by-4 matrix into
[zeros(4,1) triu(A)] + ... %# lower and upper parts so you
[eye(4) zeros(4)]; %# can insert the diagonal ones
%# Store A in a variable or perform some computation with it here
end
Here is another solution (with minimal looping):
%# generate all possible variation of first/second halves
z = -[0 1 1; 1 0 1; 1 1 0; 1 1 1]; n = -sum(z,2);
h1 = {
[ ones(4,1) z(:,1:3)] ;
[z(:,1:1) ones(4,1) z(:,2:3)] ;
[z(:,1:2) ones(4,1) z(:,3:3)] ;
[z(:,1:3) ones(4,1) ] ;
};
h2 = arrayfun(#(i) unique(perms([zeros(1,4-i) ones(1,i)]),'rows'), (1:2)', ...
'UniformOutput',false);
%'# generate all possible variations of complete rows
rows = cell(4,1);
for r=1:4
rows{r} = cell2mat( arrayfun( ...
#(i) [ repmat(h1{r}(i,:),size(h2{n(i)-1},1),1) h2{n(i)-1} ], ...
(1:size(h1{r},1))', 'UniformOutput',false) );
end
%'# generate all possible matrices (pick one row from each to form the matrix)
sz = cellfun(#(M)1:size(M,1), rows, 'UniformOutput',false);
[X1 X2 X3 X4] = ndgrid(sz{:});
matrices = cat(3, ...
rows{1}(X1(:),:), ...
rows{2}(X2(:),:), ...
rows{3}(X3(:),:), ...
rows{4}(X4(:),:) );
matrices = permute(matrices, [3 2 1]); %# 4-by-8-by-104976
%#clear X1 X2 X3 X4 rows h1 h2 sz z n r
Next you can access the 4-by-8 matrices as:
>> matrices(:,:,500)
ans =
1 -1 -1 -1 0 1 0 1
-1 1 -1 0 0 0 1 0
0 -1 1 -1 0 0 1 0
0 -1 -1 1 0 0 0 1
We could also confirm that all rows in all matrices sum to zero:
>> all(all( sum(matrices,2)==0 ))
ans =
1