matlab - creating matrix with zero rows and one on index - matlab

i have a vector a = [1; 6; 8]
and want to create a matrix with n columns and size(a,1) rows.
Each i'th row is all zeros but on the a(i) index is one.
>> make_the_matrix(a, 10)
ans =
1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0

use sparse
numCol = 10; % number of colums in output matrix, should not be greater than max(a)
mat = sparse( 1:numel(a), a, 1, numel(a), numCol );
if you want a full matrix just use
full(mat)

Here is my first thought:
a = [1;6;8];
nCols = 10;
nRows = length(a);
M = zeros(nRows,nCols);
M(:,a) = eye(nRows)
Basically the eye is assigned to the right columns of the matrix.

Related

How to assign a matrix to the diagonals of another matrix in matlab

I have a matrix D = zeros (30, 432); i want to assign d = [ 1 1 0 0; 0 0 1 1; 0 0 0 0];
to the diagonals of matrix D. i have the code below but it doesn't allow me to assign d for every diagonal values in D.
[N,~,P,Q]=size(D);
diagIndex=repmat(logical(eye(N)),[1 1 P Q]);
D(diagIndex)=d;
The output for 30x432 matrix would be like :
d 0 0 0
0 d 0 0
0 0 d 0
0 0 0 d
You can use spdiags to create a diagonal [10 x 108] sparse matrix then use kron to scale and fill the matrix.
d = [ 1 1 0 0; 0 0 1 1; 0 0 0 0]
size_D=[30, 432];
sz = size_D./size(d);
diagonal = spdiags(ones(sz(1),1),0,sz(1),sz(2));
result = kron(diagonal ,d);

Create a neighbourhood graph from a given binary matrix using matlab

I am trying to create a neighbourhood graph from a given binary matrix B. Neighbourhood graph (A) is defined as an adjacency matrix such that
(A(i,j) = A(j,i) = 1)
if the original matrix B(i) = B(j) = 1 and i and j are adjacent to each (left, right, up, down or diagonal). Here I used the linear subscript to access the original matrix B. For example, consider the below matrix
B = [ 0 1 0;
0 1 1;
0 0 0 ];
My A will be a 9 * 9 graph as given below
A = [ 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 1 0;
0 0 0 1 0 0 0 1 0;
0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0;
0 0 0 1 1 0 0 0 0;
0 0 0 0 0 0 0 0 0 ];
Since in the original B matrix, B(4), B(5) and B(8) are adjacent with corresponding entries 1, the adjacency matrix A has 1 at A(4,5), A(5,4), A(4,8), A(8,4), A(5,8) and A(8,5).
How can I create such an adjacency matrix A given the matrix B in an efficient way?
This doesn't require any toolbox, and works for square or rectangular matrices. It uses array operations with complex numbers.
Consider a binary matrix B of size M×N.
Create an M×N matrix, t, that contains the complex coordinates of each nonzero entry of B. That is, entry t(r,c) contains r+1j*c if B(r,c) is nonzero, and NaN otherwise.
Compute an M*N×M*N matrix, d, containing the absolute difference for each pair of entries of B. Pairs of entries of B that are nonzero and adjacent will produce 1 or sqrt(2) in matrix d.
Build the result matrix, A, such that it contains 1 iff the corresponding entry in d equals 1 or sqrt(2). Equivalently, and more robust to numerical errors, iff the corresponding entry in d is between 0 and 1.5.
Code:
B = [0 1 0; 0 1 1; 0 0 0]; % input
t = bsxfun(#times, B, (1:size(B,1)).') + bsxfun(#times, B, 1j*(1:size(B,2)));
t(t==0) = NaN; % step 1
d = abs(bsxfun(#minus, t(:), t(:).')); % step 2
A = d>0 & d<1.5; % step 3
To get B back from A:
B2 = zeros(sqrt(size(A,1)));
B2(any(A,1)) = 1;
Here is a solution using image processing toolbox* that creates sparse matrix representation of the adjacency matrix:
B = [ 0 1 0;
0 1 1;
0 0 0 ]
n = numel(B);
C = zeros(size(B));
f = find(B);
C(f) = f;
D = padarray(C,[1 1]);
%If you don't have image processing toolbox
%D = zeros(size(C)+2);
%D(2:end-1,2:end-1)=C;
E = bsxfun(#times, im2col(D,[3 3]) , reshape(B, 1,[]));
[~ ,y] = find(E);
result = sparse(nonzeros(E),y,1,n,n);
result(1:n+1:end) = 0;
*More efficient implementation of im2col can be found here.

Which lines have values different from zero - matlab

I have a matrix of zeros and ones. Any given column of the matrix is either full of zeros or has a single one.
E.g.:
A = [0 0 0 0 0;
1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 1];
I want to get vector B that gives me the line position of each 1. If there is no 1 on the column it should give me the maximum number of rows. Eg:
B = [2 5 4 5 5];
Any easy way of getting this?
A possible solution with matrix multiplication:
A = [0 0 0 0 0;
1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 1];
[r ,~] = size(A);
B = (1:r) * A;
B(B==0)=r;
comparison with other method:
n = 9000;
ro = randperm(n,4000);
co = randperm(n , 4000);
A = accumarray([ro(:) co(:)],1);
disp('------matrix multiplication---------:')
tic
[r ,~] = size(A);
B = (1:r) * A;
B(B==0)=r;
toc
disp('------find---------:')
tic
[r,~]=find(A);
B = double(any(A));
B(B==1)= r; B(B==0)=n;
toc
result:
------matrix multiplication---------:
Elapsed time is 0.0569789 seconds.
------find---------:
Elapsed time is 0.252345 seconds.
You can use the two-output version of max, which gives the position of each maximum. For columns consisting of only zeros the maximum will be in the first row, so you need to correct this by checking if the found maximum was 0 or 1
[m, result] = max(A, [], 1); % maximum of each column, and its row index
result(~m) = size(A, 1); % if the maximum was 0: modify result

Iteratively and randomly adding ones to a binary vector in matlab

In each iteration I want to add 1 randomly to binary vector,
Let say
iteration = 1,
k = [0 0 0 0 0 0 0 0 0 0]
iteration = 2,
k = [0 0 0 0 1 0 0 0 0 0]
iteration = 3,
k = [0 0 1 0 0 0 0 1 0 0]
, that goes up to length(find(k)) = 5;
Am thinking of for loop but I don't have an idea how to start.
If it's important to have the intermediate vectors (those with 1, 2, ... 4 ones) as well as the final one, you can generate a random permutation and, in your example, use the first 5 indices one at a time:
n = 9; %// number of elements in vector
m = 5; %// max number of 1's in vector
k = zeros(1, n);
disp(k); %// output vector of all 0's
idx = randperm(n);
for p = 1:m
k(idx(p)) = 1;
disp(k);
end
Here's a sample run:
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1
1 0 0 1 0 0 0 0 1
1 0 0 1 1 0 0 0 1
1 1 0 1 1 0 0 0 1
I wouldn't even use a loop. I would generate a random permutation of indices that sample from a vector going from 1 up to the length of k without replacement then just set these locations to 1. randperm suits the task well:
N = 10; %// Length 10 vector
num_vals = 5; %// 5 values to populate
ind = randperm(N, num_vals); %// Generate a vector from 1 to N and sample num_vals values from this vector
k = zeros(1, N); %// Initialize output vector k to zero
k(ind) = 1; %// Set the right values to 1
Here are some sample runs when I run this code a few times:
k =
0 0 1 1 0 1 1 0 0 1
k =
1 0 0 0 1 0 1 1 0 1
k =
1 0 0 0 1 0 1 1 0 1
k =
0 1 1 1 0 0 1 0 0 1
However, if you insist on using a loop, you can generate a vector from 1 up to the desired length, randomly choose an index in this vector then remove this value from the vector. You'd then use this index to set the location of the output:
N = 10; %// Length 10 vector
num_vals = 5; %// 5 values to populate
vec = 1 : N; %// Generate vector from 1 up to N
k = zeros(1, N); %// Initialize output k
%// Repeat the following for as many times as num_vals
for idx = 1 : num_vals
%// Obtain a value from the vector
ind = vec(randi(numel(vec), 1));
%// Remove from the vector
vec(ind) = [];
%// Set location in output to 1
k(ind) = 1;
end
The above code should still give you the desired effect, but I would argue that it's less efficient.

Insert an identity matrix into a larger dimension of null matrix

Suppose i have an identity matrix .
I=eye(3)
which will produce
I = [1 0 0
0 1 0
0 0 1]
Now i want to insert I into a (5X5) null matrix such that my result will be
N = [0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1]
How could i achieve this efficiently .Thanks in advace
With the Image processing toolbox, this could be done using padarray like this:
padarray(eye(3), [2 2], 'pre');
padarray pads an array with zeros. The [2 2] part says how many zeros to pad it with, in this case 2 rows and 2 columns. pre means you want it in front of the matrix, not after it (post).
Without it, you need to tweak it a bit more. One option could be to create an identity matrix of the full size, then make the first elements zero:
m = 5; %// size of matrix
n = 3; %// size of identity matrix
a = eye(m);
a(1:m-n,1:m-n) = 0;
a =
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
... or:
a = zeros(m);
a(m-n+1:m,m-n+1:m) = eye(n)
... or using sparse:
full(sparse(m-n+1:m,m-n+1:m,1))
Alternatively,
m = 5;
n = 3;
a = diag( [zeros(1, m-n), ones(1,n)] );