I have this Reduced Row Echelon Form (RREF) matrix:
1 -2 0 1 1
0 0 1 0 -1
0 0 0 0 0
0 0 0 0 0
Is there a way to get the pivot points in Matlab? I know that it will be columns 1 and 3, but I am not sure how I can do this in Matlab.
For a Reduced Row Echelon Form matrix;
The first non-zero entry in any row is the number 1, these are called pivots (1)
If you assume that your matrix is already in RREF then we don't care about what each value is, only if it is 0 or not, so for some RREF matrix A:
A = logical(A);
Then we can find the first element in each row which is non-zero using max
[v,col] = max(A,[],2);
Finally we can remove values from col where v=0, i.e. rows which are entirely 0, leaving the pivots piv:
piv = col( v > 0 );
For your example, this returns col = [1; 3]
You could do this in one line, but it's not pretty
[~,piv] = max( logical(A(any(A,2),:)), [], 2 );
(1): https://www.math.fsu.edu/~bellenot/class/f08/lalab/other/rref2.pdf
Related
I have a logical 1-by-n vector with sum m. Now, I need to convert it into a matrix m-by-n in a way that the row sum is equal 1.
vector (1-by-8) with sum 4
[0 1 0 0 1 0 1 1]
matrix (4-by-8) with row sum 1
[0 1 0 0 0 0 0 0;
0 0 0 0 1 0 0 0;
0 0 0 0 0 0 1 0;
0 0 0 0 0 0 0 1]
Is there a mathematically efficient way without calculating the sum, creating a empty matrix, loop through the vector and adding the 1s row by row?
I think that in that case, given your input, you don't even need to calculate the sum.
You can define an identity matrix of size n, then use your input vector to sample the required rows out of it:
I = eye(n);
y = I(x, :) ; % Output Matrix. x is the input vector
Here's another method, using sparse:
matrix = full(sparse(1:m, find(vector), 1, m, n));
I have a matrix,
A = [ 0 0 0 0 0 0 1 1 1 1 0 0; 0 0 0 0 0 1 1 1 1 0 0 0; 0 0 0 0 0 0 1 1 1 1 0 0]
My question is, how to find the first '1' in each row. I want the output will show like this:
B = [7; 6; 7]
Meaning that, for the first row, the number 1 found on column number 7, second row found in column number 6 and so on.
You can use the second output of max, which gives the position of the maximum:
v = 1; % desired value
[~, B] = max(A==v, [], 2); % position of maxima along the second dimension
As a bonus, if there can be rows that don't contain the desired value, you can output 0 for those rows as follows:
[m, B] = max(A==v, [], 2);
B = B.*m;
Find cumulative sum of each row of A and use find to get the row and column subscripts of ones and then order the column subscripts according to rows to get the desired matrix B.
[rind,cind] = find(cumsum(A,2)==1);
[~, rind] = unique(rind);
B = cind(rind);
Is there a vectorization way of returning the index of the last K nonzero elements of each row of a matrix?
For example, my matrix only contains 0 and 1 and the last column of each row is always 1. Then I want to find the index of the last K, where K>1, nonzero elements of each row. If a row only has M (less than K) nonzero elements, then the index for that row is just the index of the last M nonzero element. e.g.
A = [0 1 0 1;
1 1 0 1;
1 1 1 1;
0 0 0 1]
And my K = 2, then I expected to return a matrix such that
B = [0 1 0 1;
0 1 0 1;
0 0 1 1;
0 0 0 1]
Namely B is originally a zero matrix with same shape as A, then it copies each row of A where the corresponding column starts from the index of the last K non-zero element of the row of A (and if in one row of A there is only M < K non-zero element, then it starts from the index of the last M non-zero element of that row of A)
Knowing that elements are only 0 or 1, you can make a mask using cumsum on the flipped matrix A and throw away values with a cumulative sum greater than k:
A = [0 1 0 1;1 1 0 1;1 1 1 1;0 0 0 1]
k = 2;
C = fliplr(cumsum(fliplr(A), 2)); % take the cumulative sum backwards across rows
M = (C <= k); % cumsum <= k includes 0 elements too, so...
B = A .* M % multiply original matrix by mask
As mentioned in the comments (Thanks #KQS!), if you're using a recent version of MATLAB, there's a direction optional parameter to cumsum, so the line to generate C can be shortened to:
C = cumsum(A, 2, 'reverse');
Results:
A =
0 1 0 1
1 1 0 1
1 1 1 1
0 0 0 1
B =
0 1 0 1
0 1 0 1
0 0 1 1
0 0 0 1
knowing that find function can get indices of last k elements, we can use bsxfun to apply find to rows of a matrix to find which element in each row satisfy the condition. find again used to extract rows and columns of nonzero elements of the resultant matrix, so reducing size of data and complexity of operations. then save the result to a sparse matrix then convert to full matrix:
A = [0 1 0 1;
1 1 0 1;
1 1 1 1;
0 0 0 1]
k = 2;
[row , col]= size(A);
last_nz = bsxfun(#(a,b)find(a,b,'last'),A',(repmat(k, 1, row))); %get indices of last two nonzero elements for each row
[~,rr,cc]=find(last_nz); %get columns and rows of correspondong element for whole matrix
B = full(sparse(rr,cc,1));
I have a binary sparse matrix H of size 600*1200 constructed by concatenating square permutation matrices of size 200, thus sparse matrix have 3 ones in each column and 6 ones in each row. Now am trying to transform the matrix into reduced echelon form.
This is my code:
[m,n]=size(H);
for i=1:m
ind=find(H(:,i),1,'last');
if ind<=i
continue;
end
if ind~=i
temp=H(ind,:);
H(ind,:)=H(i,:);
H(i,:)=temp;
end
I=find(H(:,i));
% Guassian elimination
for j=1:length(I)
if I(j)~=i
H(I(j),:)=mod(H(I(j),:)+H(i,:),2);
end
end
end
But whichever H matrix generated, I can't get rid of other entries at 400th column,
how can I fix this, help
Since Gaussian elimination does not involve rearrangement of columns, the first 600 columns of the resulting matrix will only form the identity matrix if the first 600 columns of the original matrix were linearly independent. Otherwise, you are going to have "short" columns with other entries in them, as the Wikipedia article shows.
The way your matrix is structured, the first 400 columns are guaranteed to be linearly dependent. Indeed, the sum of the first 200 columns is the all-1 vector, and so is the sum of the columns 201-400. This is why you are seeing these entries in the 400th column.
To create identity matrix on the left you need to rearrange columns. One way, which looks a bit redundant but is very easy to code, is to
run your algorithm
rearrange columns (it's easy to identify the desired columns after rref)
do rref again.
Here is the code that does steps 2-3.
for i = 1:m
j = find(H(i,:),1,'first');
[H(:,i), H(:,j)] = deal(H(:,j), H(:,i));
end
H = rref(H)
Sample input into rref:
1 0 1 0 1
0 1 0 0 1
1 0 1 1 0
0 0 0 0 1
Output of your code:
1 0 1 1 0
0 1 0 0 1
0 0 0 1 1
0 0 0 0 1
After the column swap and second rref:
1 0 0 0 1
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
Given a binary matrix in which every row and column contains exactly only one 1, I need to rearrange the matrix columnwise so that it will become an identity matrix. For example, given a binary matrix:
Binary = [ 0 1 0 0 0
0 0 1 0 0
1 0 0 0 0
0 0 0 0 1
0 0 0 1 0 ]
To get the identity matrix we rearrange the column as 2 3 1 5 4.
How can we optimally rearrange the columns for any given arbitrary square binary matrix?
A very simple way to do this is to use the function FIND like so:
[index,~] = find(Binary.'); %'# Transpose the matrix and find the row indices
%# of the non-zero entries
And you can test that it work as follows:
>> Binary(:,index)
ans =
1 0 0 0 0 %# Yup, that's an identity matrix alright!
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
OLD APPROACH:
This isn't as compact or efficient as the above solution, but you could also transpose the matrix and use SORTROWS to sort the columns (now transposed into the rows) and return the sort indices. This will actually sort values in ascending order, which will give you an anti-diagonal matrix, so you will want to flip the vector of indices using FLIPUD. Here's the code:
[~,index] = sortrows(Binary.'); %'# Transpose and sort the matrix
index = flipud(index); %# Flip the index vector
If you know the matrix can be manipulated into an identity matrix, why don't you just create an identity matrix with the same dimensions?
identity_matrix=eye(length(Binary))