Matlab: Access matrix elements using indices stored in other matrices - matlab

I am working in matlab. I have five matrices in ,out, out_temp,ind_i , ind_j, all of identical dimensions say n x m. I want to implement the following loop in one line.
out = zeros(n,m)
out_temp = zeros(n,m)
for i = 1:n
for j = 1:m
out(ind_i(i,j),ind_j(i,j)) = in(ind_i(i,j),ind_j(i,j));
out_temp(ind_i(i,j),ind_j(i,j)) = some_scalar_value;
end
end
It is assured that the values in ind_i lies in range 1:n and values in ind_j lies in range 1:m.
I believe a way to implement line 3 would give the way to implement line 4 , but I wrote it to be clear about what I want.

Code
%// Calculate the linear indices in one go using all indices from ind_i and ind_j
%// keeping in mind that the sizes of both out and out_temp won't go beyond
%// the maximum of ind_i for the number of rows and maximum of ind_j for number
%// of columns
ind1 = sub2ind([n m],ind_i(:),ind_j(:))
%// Initialize out and out_temp
out = zeros(n,m)
out_temp = zeros(n,m)
%// Finally index into out and out_temp and assign them values
%// using indiced values from in and the scalar value respectively.
out(ind1) = in(ind1);
out_temp(ind1) = some_scalar_value;

Related

Matlab: What is the most efficient way to add zero rows (or column) to a sparse matrix?

Suppose I have an N x N sparse matrix. Take for example A = speye(N).
My general question is: what is the most efficient way to add zero rows (or column) to a sparse matrix?
Adding jj columns on the right side of the matrix and/or adding ii rows at the bottom of the matrix simply changes the size of the sparse matrix. So in code this would be
N=2;
A=speye(N);
[rows,cols,vals] = find(A);
% Add ii = 3 zero rows at the bottom
% and jj = 2 zero columns at the left of A
ii = 3; jj=2;
B = sparse(rows,cols,vals,N+ii,N+jj);
Adding columns on the left and at the top, also changes the indices.
N=2;
A=speye(N);
[rows,cols,vals] = find(A);
% Add ii = 3 zero rows at the top
% and jj = 2 zero columns at the right of A
ii = 3; jj=2;
B = sparse(rows+ii,cols+jj,vals,N+ii,N+jj);
Is there a more efficient way, for either of the two cases? For example, can I skip somehow finding the non-zero elements of A?
You can add a column as you would with a standard matrix
% Create a sparse matrix
A = speye(3);
% Add a column of zeros to the end
A(:, end+1) = 0;
Note that find will still only return the 2 non-zero values, but size(A)=[2,3], i.e we've successfully added a column.
Variants:
% Still adding a column on the right, by concatenating with another sparse matrix.
% However: this is less memory efficient with A on the right hand side
A = [A, sparse(3,1)];
% Adding column on the left
A = [sparse(3,1), A]; % comma is equivalent of 'horzcat'
% Adding a row on the top
A = [sparse(1,size(A,2)); A]; % semi-colon is equivalent of 'vertcat'

Fill a zeros matrix with specific numbers of 1

I'm facing a problem. I have a zeros matrix 600x600. I need to fill this matrix with 1080 1s randomly. Any suggestions?
Or, use the intrinsic routine randperm thusly:
A = zeros(600);
A(randperm(600^2,1080)) = 1;
A = sparse(600,600); %// set up your matrix
N=1080; %// number of desired ones
randindex = randi(600^2,N,1); %// get random locations for the ones
while numel(unique(randindex)) ~= numel(randindex)
randindex = randi(600^2,N,1); %// get new random locations for the ones
end
A(randindex) = 1; %// set the random locations to 1
This utilises randi to generate 1080 numbers randomly between 1 and 600^2, i.e. all possible locations in your vectors. The while loop is there in case it happens that one of the locations occurs twice, thus ending up with less than 1080 1.
The reason you can use a single index in this case for a matrix is because of linear indexing.
The big performance difference with respect to the other answers is that this initialises a sparse matrix, since 1080/600^2 = 0.3% is very sparse and will thus be faster. (Thanks to #Dev-iL)
This is one way to do it,
N = 1080; % Number of ones
M = zeros(600); % Create your matrix
a = rand(600^2,1); % generate a vector of randoms with the same length as the matrix
[~,asort] = sort(a); % Sorting will do uniform scrambling since uniform distribution is used
M(asort(1:N)) = 1; % Replace first N numbers with ones.

Matlab code for generating a particular class of matrices

I need to generate all square matrices of order n with given properties.
Matrices are symmetric.
Entries are 0 and 1.
Diagonal elements are zeros.
I am using Matlab2012b. Can you help me with the code?
I was trying to write it down. It needs a long sequences of for loops. Any simpler technique?
Try this:
N = 4; %// matrix size
M = (N^2-N)/2; %// number of values to fill in each matrix
P = 2^M; %// number of matrices
x = dec2bin(0:P-1)-'0'; %// each row contains the values of a matrix, "packed" in a vector
result = NaN(N,N,P); %// preallocate
for k = 1:P
result(:,:,k) = squareform(x(k,:)); %// unpack values
end
The matrices are result(:,:,1), result(:,:,2) etc.

How to find N values of 3D matrix that satisfy condition

I have a 3D array that is denoted by features. Each element of feature is a number x. Now I will get that number and calculate g(x) and f(x) of the number (g and f are functions of x). My problem is how to get N maximization of absolute value between g(x) and f(x). The function will return an array with N elements x. But I don't know how to get them. Could you help me?
This is my code:
%features is 3D array
%N is elements that we need
%Fs,sigmas,thetas are size of the array
% return N elements of features that maximization abs(f_s-g_s)
function features_filter=gabor_sort(features,N,Fs,sigmas,thetas)
for k = 1:numel(sigmas)
for j = 1:numel(Fs)
for i = 1:numel(thetas)
x= features(:,:,k,j,i);
f_x=x.^2;
g_x=x.^3+1;
s1=abs(f_x-g_x);
%%Do something in here to get maximization of s1
end
end
end
end
This isn't a problem. Create two matrices that will store the features we get for each combination of sigma, Fs and theta, as well as place your absolute values for each feature in this matrix, and when you're done, sort these distances in descending order. We can then use the second parameter of sort to give us the location of the features that maximize this distance. In other words, do this:
%features is 3D array
%N is elements that we need
%Fs,sigmas,thetas are size of the array
% return N elements of features that maximization abs(f_x-g_x)
function features_filter=gabor_sort(features,N,Fs,sigmas,thetas)
s1 = []; % s1 array to store our distances
xFeatures = []; %// Features to return
for k = 1:numel(sigmas)
for j = 1:numel(Fs)
for i = 1:numel(thetas)
x = features(:,:,k,j,i);
xFeatures = cat(3,xFeatures,x); %// Stack features in a 3D matrix
x = x(:); %// Convert to 1D as per your comments
f_x=mean(x.^2); %// Per your comment
g_x=mean(x.^3+1); %// Per your comment
s1 = [s1 abs(f_x-g_x)]; %// Add to s1 array
end
end
end
[~,sortInd] = sort(s1, 'descend');
%// Return a 3D matrix where each slice is a feature matrix
%// The first slice is the one that maximized abs(f_x - g_x) the most
%// The second slice is the one that maximized abs(f_x - g_x) the second most, etc.
features_filter = xFeatures(:,:,sortInd(1:N));
Minor note: This code is untested. I don't have access to your data, so I can't really reproduce. Hope this works!

How can I concatenate many column vectors into one matrix?

I want to concatenate 100 column vectors into one matrix. The code is the following:
for i = 1:100
X = mean(TMP(i).SonarReturnData.BeamsOutput(1:200, 25:35), 2);
end
What I want is to concatenate all 100 column vectors (each 200x1 length vectors) into one matrix (which should become a 200x100 matrix). I tried to use C = cat(2,X(:)), but it didn't work. Does anyone have an idea? Thank you.
Just pre-allocate X with your desired 200x100 size and then index into columns of X appropriately in your loop. I.e.,
X = zeros(200, 100);
for i = 1:100
X(:,i) = mean(TMP(i).SonarReturnData.BeamsOutput(1:200, 25:35), 2);
end