How to find all linear columns dependency in matrix - matlab

I want to find the index of all linear columns in matrix. The output is a vector in which gives 1 for independent columns and -1 for all linear dependency columns. For example, I have a matrix A that is
A =
1 0 0 0 0 1 1
1 0 0 1 0 1 1
1 1 1 0 1 1 1
1 1 1 0 1 1 0
We can see that column dependency are 1,2,3,5,6. Hence my expected result are
output=[-1 -1 -1 1 -1 -1 1];
And the independent matrix remains
A =
0 1
1 1
0 1
0 0
How to implement it by matlab ?
How about with linear rows?

I think you are looking for something like this -
out = ones(1,size(A,2))
out(sum(all(bsxfun(#eq,A,permute(A,[1 3 2])),1),2)>=2)=-1
So, basically for each column, it finds if there are any other matching columns and if there are, it identifies that as a "dependent" (from what I could gather as the definition for this problem) column.
Output -
out =
-1 -1 -1 1 -1 -1 1
For finding "dependency" across rows, use this -
out = ones(1,size(A,1))
out(sum(all(bsxfun(#eq,A,permute(A,[3 2 1])),2),1)>=2)=-1

Related

Create a matrix in MATLAB with limited number of elements

I would like to create an 12*3 matrix in MATLAB that has only 2 non-zero elements in each row. How should I generate a code to get all the possible conditions. The non-zero elements can take on any integers from 1 to 2.
If you want all the possible combination without repetition for 0 and with repetition for 1 and 2:
% Number of integer with repetition.
n = 2
% Generate all the possible combination of 1 and 2.
[x1,x2] = meshgrid(1:n,1:n);
M = [zeros(n^2,1),x1(:),x2(:)];
% We shift the 0 column n time.
M = cell2mat(arrayfun(#(x) circshift(M,x,2),0:n,'UniformOutput',0).');
Result:
M =
0 1 1
0 1 2
0 2 1
0 2 2
1 0 1
2 0 1
1 0 2
2 0 2
1 1 0
1 2 0
2 1 0
2 2 0

Is there a fast way to count occurrences of items in a matrix and save them in another matrix without using loops?

I have a time-series matrix X whose first column contains user ID and second column contains the item ID they used at different times:
X=[1 4
2 1
4 2
2 3
3 4
1 1
4 2
5 3
2 1
4 2
5 4];
I want to find out which user used which item how many times, and save it in a matrix Y. The rows of Y represent users in ascending order of ID, and the columns represent items in ascending order of ID:
Y=[1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1]
The code I use to find matrix Y uses 2 for loops which is unwieldy for my large data:
no_of_users = size(unique(X(:,1)),1);
no_of_items = size(unique(X(:,2)),1);
users=unique(X(:,1));
Y=zeros(no_of_users,no_of_items);
for a=1:size(A,1)
for b=1:no_of_users
if X(a,1)==users(b,1)
Y(b,X(a,2)) = Y(b,X(a,2)) + 1;
end
end
end
Is there a more time efficient way to do it?
sparse creates a sparse matrix from row/column indices, conveniently accumulating the number of occurrences if you give a scalar value of 1. Just convert to a full matrix.
Y = full(sparse(X(:,1), X(:,2), 1))
Y =
1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1
But it's probably quicker to just use accumarray as suggested in the comments:
>> Y2 = accumarray(X, 1)
Y2 =
1 0 0 1
2 0 1 0
0 0 0 1
0 3 0 0
0 0 1 1
(In Octave, sparse seems to take about 50% longer than accumarray.)

finding the frequency of each row (2)

Per my previous question, I have several mx2 matrices with rows from (0,1), (-1,0), (0,1), (0,-1), (1,1), (-1,1), (1,-1),(-1,-1) and I would like to find the frequency of each of above coordinates, I used unique and hisc to give me the frequency of each row. Now, since I would like to compare different matrices, I would like for each matrix have a corresponding output of 8 rows, where each row indicates the number of times that each of above coordinates appear. In particular, if e.g (0,1) is not among the rows of my matrix, I would like to see zero frequency.
For instance, if A=[1 1; 0 1; 1 0; -1 1;-1 1;0 1;0 1]
I would like to see something like:
-1 -1 0
-1 0 0
-1 1 2
0 -1 0
0 1 3
1 -1 0
1 0 1
1 1 1
Is there a way to do it? Thanks.
A = [ 1 1
0 1
1 0
-1 1
-1 1
0 1
0 1 ];
rows = [ -1 -1
-1 0
-1 1
0 -1
0 1
1 -1
1 0
1 1 ];
count = sum(squeeze(all(bsxfun(#eq, A.', permute(rows, [2 3 1])))));
Of course, if you need the result in the form shown in your question, just build the matrix result = [rows count.'].

Logical operations on matrices columns.

Let say that I have 1 matrix with numbers (0,1). How can i create new matrix that is the result of a logical operation among the columns?
eg. A =
0 0 0 1 0
1 1 1 1 1
0 1 1 0 0
0 0 0 0 1
1 0 0 1 0
1 1 1 1 1
If all elements of **rows** are equal to 1 - 1, if not - 0.
(like AND operation)
Ans= 0
1
0
0
0
1
Thanks!
To solve your problem this would work -
all(A,2)
If you were looking to set elements based on the columnwise data in A, you would do this -
all(A,1)
More info on all, must serve you well.

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