How to efficiently select only certain columns of a triangular matrix - matlab

I have the following problem:
I need certain columns of a huge triangular 1-0 matrix.
E.g.
Matrix =
1 0 0 0
1 1 0 0
1 1 1 0
1 1 1 1
Index =
[1 4]
Result =
1 0
1 0
1 0
1 1
I figured the easiest way would be:
index = [10 20 300] %arbitrary index
buf = tril(ones(60000,60000))
matr = buf(:,index)
However, this does not work as the buffer matrix is too large and leads to MATLAB throwing an error. Thus, this approach is blocked.
How can I solve that problem efficiently? (E.g. it would be trivial by just looping over the index array and concatenating self-made rows, however this would be slow and I was hoping for a faster approach)
The index array will not be larger than 1/10th of the available columns.

If the matrix contains ones on the main diagonal and below, and zeros otherwise, you can do it as follows without actually generating the matrix:
N = 10; % number of rows of (implicit) matrix
Index = [1 4]; % column indices
Result = bsxfun(#ge, (1:N).', Index);

Related

Need help in creating a matrix with exactly one 1 in each row/column at different locations

This code generates a matrix having 1 in each row and this 1 may be on same locations in rows.
I want for each row the location of 1 must be different i.e 1 must not overlap in columns.
Suppose you want the result matrix to be of size [m, n].
First, randomly select , for each column, the index of the 1
idx = randi(m, 1, n);
Second, allocate an all-zero matrix of size [m,n]
res = zeros(m,n);
Finally, set the corresponding entries to one:
res( sub2ind([m,n], idx, 1:n) ) = 1;
An example result for [3,4] matrix:
res =
0 0 1 0
0 0 0 0
1 1 0 1

Inserting columns to a matrix in Matlab

I'd like to insert columns to a matrix, but the insertion column positions within the matrix differ by row. How can I do this without using for-loop?
Following is a simplified example in MATLAB;
From A,X,P, I want to get APX without using for-loop.
>> A = zeros(4,5) % inclusive matrix
A =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
>> X = [9,8;5,7;8,3;6,7] % data to insert
X =
9 8
5 7
8 3
6 7
>> P = [3;2;4;1] % insertion position within the matrix
P =
3
2
4
1
>> APX = [0,0,9,8,0;0,5,7,0,0;0,0,0,8,3;6,7,0,0,0] % what I want
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
It's simply determining the right column-major indices to access the matrix so you can populate it with your desired values. This first requires generating the right row and column values to access the right positions in APX so you can use X to populate those positions.
Using P, each element tells you which column you should start populating for each row of X. You will need to generate column indices in increasing order up to as many columns as there are in X. To generate the row indices, simply create a matrix that is the same size as X where each column spans from 0 up to as many rows as there are in X minus 1 (i.e. 0:size(X,2)-1). This matrix gives you the correct offsets so that you can take P and add it with this matrix. Once you do that you will have a column index matrix that tells you specifically where each element should go with regards to the columns of the output matrix per row of P. Finally, use sub2ind to generate the column-major indices using the rows and columns generated above to place X in APX.
In other words:
P = [3;2;4;1];
X = [9,8;5,7;8,3;6,7];
rowInd = repmat((1:size(X,1)).', 1, size(X,2)); %'
colInd = bsxfun(#plus, P, 0:size(X,2)-1);
APX = zeros(size(X,1), max(colInd(:)));
APX(sub2ind(size(APX), rowInd, colInd)) = X;
To generate the row locations, we use repmat to create a matrix that is the same size as X where each column spans from 1 up to as many rows as X. To generate the column locations, we use bsxfun to create a matrix where each column is the vector P but increasing by 1 per column. We then create APX to be of compatible size then use sub2ind to finally populate the matrix.
With your above test inputs, we get:
APX =
0 0 9 8 0
0 5 7 0 0
0 0 0 8 3
6 7 0 0 0
Minor Note
You really should actually try using loops before trying it vectorized. Though using loops was slow in previous versions of MATLAB, MATLAB R2015b has an improved JIT engine where loops are now competitive. You should time your code using loops and ensuring that it is justifiable before switching to vectorized implementations.

Finding all possible “lists” of possible pairs in Matlab

I have been thinking about a problem for the last few days but as I am a beginner in MATLAB, I have no clue how to solve it. Here is the background. Suppose that you have a symmetric N×N matrix where each element is either 0 or 1, and N = (1,2,...,n).
For example:
A =
0 1 1 0
1 0 0 1
1 0 0 0
0 1 0 0
If A(i,j) == 1, then it is possible to form the pair (i,j) and if A(i,j)==0 then it is NOT possible to form the pair (i,j). For example, (1,2) is a possible pair, as A(1,2)==A(2,1)==1 but (3,4) is NOT a possible pair as A(3,4)==A(4,3)==0.
Here is the problem. Suppose that a member of the set N only can for a pair with at most one other distinct member of the set N (i.e., if 1 forms a pair with 2, then 1 cannot form a pair with 3). How can I find all possible “lists” of possible pairs? In the above example, one “list” would only consist of the pair (1,2). If this pair is formed, then it is not possible to form any other pairs. Another “list” would be: ((1,3),(2,4)). I have searched the forum and found that the latter “list” is the maximal matching that can be found, e.g., by using a bipartite graph approach. However, I am not necessarily only interested to find the maximal matching; I am interested in finding ALL possible “lists” of possible pairs.
Another example:
A =
0 1 1 1
1 0 0 1
1 0 0 0
1 1 0 0
In this example, there are three possible lists:
(1,2)
((1,3),(2,4))
(1,4)
I hope that you can understand my question, and I apologize if am unclear. I appreciate all help I can get. Many thanks!
This might be a fast approach.
Code
%// Given data, A
A =[ 0 1 1 1;
1 0 0 1;
1 0 0 0;
1 1 0 0];
%%// The lists will be stored in 'out' as a cell array and can be accessed as out{1}, out{2}, etc.
out = cell(size(A,1)-1,1);
%%// Code that detects the lists using "selective" diagonals
for k = 1:size(A,1)-1
[x,y] = find(triu(A,k).*(~triu(ones(size(A)),k+1)));
out(k) = {[x y]};
end
out(cellfun('isempty',out))=[]; %%// Remove empty lists
%%// Verification - Print out the lists
for k = 1:numel(out)
disp(out{k})
end
Output
1 2
1 3
2 4
1 4
EDIT 1
Basically I will calculate all the the pairwise indices of the matrix to satisfy the criteria set in the question and then simply map them over the given matrix. The part of finding the "valid" indices is obviously the tedious part in it and in this code with some aggressive approach is expensive too when dealing with input matrices of sizes more than 10.
Code
%// Given data, A
A = [0 1 1 1; 1 0 1 1; 1 1 0 1; 1 1 1 0]
%%// Get all pairwise combinations starting with 1
all_combs = sortrows(perms(1:size(A,1)));
all_combs = all_combs(all_combs(:,1)==1,:);
%%// Get the "valid" indices
all_combs_diff = diff(all_combs,1,2);
valid_ind_mat = all_combs(all(all_combs_diff(:,1:2:end)>0,2),:);
valid_ind_mat = valid_ind_mat(all(diff(valid_ind_mat(:,1:2:end),1,2)>0,2),:);
%%// Map the ones of A onto the valid indices to get the lists in a matrix and then cell array
out_cell = mat2cell(valid_ind_mat,repmat(1,[1 size(valid_ind_mat,1)]),repmat(2,[1 size(valid_ind_mat,2)/2]));
A_masked = A(sub2ind(size(A),valid_ind_mat(:,1:2:end),valid_ind_mat(:,2:2:end)));
out_cell(~A_masked)={[]};
%%// Remove empty lists
out_cell(all(cellfun('isempty',out_cell),2),:)=[];
%%// Verification - Print out the lists
disp('Lists =');
for k1 = 1:size(out_cell,1)
disp(strcat(' List',num2str(k1),':'));
for k2 = 1:size(out_cell,2)
if ~isempty(out_cell{k1,k2})
disp(out_cell{k1,k2})
end
end
end
Output
A =
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Lists =
List1:
1 2
3 4
List2:
1 3
2 4
List3:
1 4
2 3
I'm sure there's a faster way to do it, but here's the obvious solution:
%// Set top half to 0, and find indices of all remaining 1's
A(triu(A)==1) = 0;
[ii,jj] = find(A);
%// Put these in a matrix for further processing
P = [ii jj];
%// Sort indices into 'lists' of the kind you defined
X = repmat({}, size(P,1),1);
for ii = 1:size(P,1)-1
X{ii}{1} = P(ii,:);
for jj = ii+1:size(P,1)
if ~any(ismember(P(ii,:), P(jj,:)))
X{ii}{end+1} = P(jj,:); end
end
end

sparse matrix parallel to the full matrix syntax of A(ind,ind)=1 in Matlab

In Matlab I can populate all combinations of elements in a full matrix by doing the following:
A=zeros(5);
ind=[1 4 5];
A(ind,ind)=1
A =
1 0 0 1 1
0 0 0 0 0
0 0 0 0 0
1 0 0 1 1
1 0 0 1 1
How can I accomplish that when my matrix A is sparse? (say A=zeros(1e6) and I only want ~1000 elements to be 1 etc...)
You can use the sparse command, as follows:
% create a 5x5 sparse matrix A, with 1's at A(ind,ind)
[row,col] = meshgrid(ind,ind); % form indexing combinations
row = row(:); % rearrange matrices to column vectors
col = col(:);
A = sparse(row, col, 1, 5, 5);
While it is possible to index sparse matrices using the conventional A(1,2) = 1 style, generally this is not a good idea. MATLAB sparse matrices are stored very differently to full matrices behind the scenes and do not support efficient dynamic indexing of this kind.
To get good performance sparse matrices should be built in one go using the sparse(i,j,x,m,n) syntax.

shift of rows among matrices matlab

I am doing a project on Particle Swarm optimization, coding in Matlab. I need to replace the rows of matrix A by some of the rows from matrix B and remove those rows from matrix B as well. How can I do that?
Put you row indices in vectors, say
indexA=[0 0 0 1 0 1 1 0].
indexB=[0 1 0 1 0 1].
Partition B into
A(indexA,:) = B(indexB,:);
B(indexB,:) = [];