MATLAB Expanding A Matrix with Zeros - matlab

I need a matrix of nxn, where the first pxp of it contains ones and rest are zeros. I can do it with traversing the cells, so I'm not asking a way to do it. I'm looking for "the MATLAB way" to do it, using built-in functions and avoiding loops etc.
To be more clear;
let n=4 and p=2,
then the expected result is:
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0
There are possibly more than one elegant solution to do it, so I will accept the answer with the shortest and most readable one.
P.S. The question title looks a bit irrelevant: I put that title because my initial approach would be creating a pxp matrix with ones, then expanding it to nxn with zeros.

The answer is creating a matrix of zeroes, and then setting part of it to 1 using indexing:
For example:
n = 4;
p = 2;
x = zeros(n,n);
x(1:p,1:p) = 1;
If you insist on expanding, you can use:
padarray( zeros(p,p)+1 , [n-p n-p], 0, 'post')

Another way to expand the matrix with zeros:
>> p = 2; n = 4;
>> M = ones(p,p)
M =
1 1
1 1
>> M(n,n) = 0
M =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0

You can create the matrix easily by concatenating horizontally and vertically:
n = 4;
p = 2;
MyMatrix = [ ones(p), zeros(p, n-p); zeros(n-p, n) ];

>> p = 2; n = 4;
>> a = [ones(p, 1); zeros(n - p, 1)]
a =
1
1
0
0
>> A = a * a'
A =
1 1 0 0
1 1 0 0
0 0 0 0
0 0 0 0

Related

Writing a loop that works for any value of N

I have a code for a 1D heat equation. Im trying to format a for loop so that the A matrix will follow a certain pattern of 1 -2 1 down the entire diagonal of a matrix that could be infinite. The pattern starts to take shape when I mess around with the initialized count at the beginning of the for loop but this changes the size of the matrix which fails the rest of the code.
My current code is below. The commented A matrix edits are what it should be.
N = 5;
%A(2,1:3) = [1 -2 1];
%A(3,2:4) = [1 -2 1];
%A(4,3:5) = [1 -2 1];
%A(5,4:6) = [1 -2 1];
A = zeros(N+1,N+1);
A(1,1) = 1;
for count=N:N+1
A(count+1,count:count+2) = [1 -2 1];
end
A(N+1,N+1) = 1;
In Matlab you can often avoid loops. In this case you can get the desired result with 2D convolution:
>> N = 6;
>> A = [1 zeros(1,N-1); conv2(eye(N-2), [1 -2 1]); zeros(1,N-1) 1]
A =
1 0 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 0 1
Or, depending on what you want,
>> A = conv2(eye(N), [1 -2 1], 'same')
A =
-2 1 0 0 0 0
1 -2 1 0 0 0
0 1 -2 1 0 0
0 0 1 -2 1 0
0 0 0 1 -2 1
0 0 0 0 1 -2
There are many simple ways of creating this matrix.
Your loop can be amended as follows:
N = 5;
A = zeros(N+1,N+1);
A(1,1) = 1;
for row = 2:N
A(row, row-1:row+1) = [1 -2 1];
end
A(N+1,N+1) = 1;
I've renamed count to row, we're indexing each row (from 2 to N, skipping the first and last rows), then finding with row-1:row+1 the three indices for that row that you want to address.
Directly indexing the diagonal and off-diagonal elements. Diagonal elements for an NxN matrix are 1:N+1:end. This is obviously more complex, I'd prefer the loop:
N = 6;
A = zeros(N,N);
A(1:N+1:end) = -2;
A(2:N+1:end-2*N) = 1; % skip last row
A(2*N+2:N+1:end) = 1; % skip first row
A(1,1) = 1;
A(N,N) = 1;
Using diag. We need to special-case the first and last rows:
N = 6;
A = diag(-2*ones(N,1),0) + diag(ones(N-1,1),1) + diag(ones(N-1,1),-1);
A(1,1:2) = [1,0];
A(end,end-1:end) = [0,1];

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.

How to permute elements of a vector by another vector to obtain a matrix of permutations

I want to obtain all the possible permutations of one vector elements by another vector elements. For example one vector is A=[0 0 0 0] and another is B=[1 1]. I want to replace the elements of A by B to obtain all the permutations in a matrix like this [1 1 0 0; 1 0 1 0; 1 0 0 1; 0 1 1 0; 0 1 0 1; 0 0 1 1]. The length of real A is big and I should be able to choose the length of B_max and to obtain all the permutations of A with B=[1], [1 1], [1 1 1],..., B_max.
Thanks a lot
Actually, since A and B are always defined, respectively, as a vector of zeros and a vector of ones, this computation is much easier than you may think. The only constraints you should respect concerns B, which shoud not be empty and it's elements cannot be greater than or equal to the number of elements in A... because after that threshold A will become a vector of ones and calculating its permutations will be just a waste of CPU cycles.
Here is the core function of the script, which undertakes the creation of the unique permutations of 0 and 1 given the target vector X:
function p = uperms(X)
n = numel(X);
k = sum(X);
c = nchoosek(1:n,k);
m = size(c,1);
p = zeros(m,n);
p(repmat((1-m:0)',1,k) + m*c) = 1;
end
And here is the full code:
clear();
clc();
% Define the main parameter: the number of elements in A...
A_len = 4;
% Compute the elements of B accordingly...
B_len = A_len - 1;
B_seq = 1:B_len;
% Compute the possible mixtures of A and B...
X = tril(ones(A_len));
X = X(B_seq,:);
% Compute the unique permutations...
p = [];
for i = B_seq
p = [p; uperms(X(i,:).')];
end
Output for A_len = 4:
p =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
1 1 0 0
1 0 1 0
1 0 0 1
0 1 1 0
0 1 0 1
0 0 1 1
1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1

How to generate a customized checker board matrix as fast as possible?

I need a function that creates a checker board matrix with M rows and N columns of P*Q rectangles. I modified the third solution from here to get that:
function [I] = mycheckerboard(M, N, P, Q)
nr = M*P;
nc = N*Q;
i = floor(mod((0:(nc-1))/Q, 2));
j = floor(mod((0:(nr-1))/P, 2))';
r = repmat(i, [nr 1]);
c = repmat(j, [1 nc]);
I = xor(r, c);
it works with no problem:
I=mycheckerboard(2, 3, 4, 3)
I =
0 0 0 1 1 1 0 0 0
0 0 0 1 1 1 0 0 0
0 0 0 1 1 1 0 0 0
0 0 0 1 1 1 0 0 0
1 1 1 0 0 0 1 1 1
1 1 1 0 0 0 1 1 1
1 1 1 0 0 0 1 1 1
1 1 1 0 0 0 1 1 1
But it's not fast enough since there are lots of calls of this function in a single run. Is there a faster way to get the result? How can I remove floating point divisions and/or calls of the floor function?
Your code is fairly fast for small matrices, but becomes less so as the dimensions get larger. Here's a one-liner using bsxfun and imresize (requires Image Processing toolbox that most have):
m = 2;
n = 3;
p = 4;
q = 3;
I = imresize(bsxfun(#xor, mod(1:m, 2).', mod(1:n, 2)), [p*m q*n], 'nearest')
Or, inspired by #AndrasDeak's use of kron, this is faster with R2015b:
I = kron(bsxfun(#xor, mod(1:m, 2).', mod(1:n, 2)), ones(p, q))
For a small bit more speed, the underlying code for kron can be simplified by taking advantage of the structure of the problem:
A = bsxfun(#xor, mod(1:m, 2).', mod(1:n, 2));
A = permute(A, [3 1 4 2]);
B = ones(q, 1, p);
I = reshape(bsxfun(#times, A, B), [m*n p*q]);
or as one (long) line:
I = reshape(bsxfun(#times, permute(bsxfun(#xor, mod(1:m, 2).', mod(1:n, 2)), [3 1 4 2]), ones(q, 1, p)), [m*n p*q]);
I suggest first creating a binary matrix for the checkerboard's fields, then using the built-in kron to blow it up to the necessary size:
M = 2;
N = 3;
P = 4;
Q = 3;
[iM,iN] = meshgrid(1:M,1:N);
A = zeros(M,N);
A(mod(iM.'+iN.',2)==1) = 1;
board = kron(A,ones(P,Q))

Compare two vectors of unequal lengths to get a logical array

I need to vectorize the following code:
a = [1 2 3 2 3 1];
b = [1 2 3];
for i = 1:length(a)
for j = 1:length(b)
r(i, j) = (a(i) == b(j));
end
end
The output r should be a logical array:
1 0 0
0 1 0
0 0 1
0 1 0
0 0 1
1 0 0
The closest I can get is:
for j = 1:length(b)
r(:, j) = (a == b(j));
end
Iterating through the shorter vector is obviously more efficient as it generates fewer for iterations. The correct solution should have no for-loops whatsoever.
Is this possible in MATLAB/Octave?
Here's a simple solution using bsxfun.
bsxfun(#eq,b,a')
ans =
1 0 0
0 1 0
0 0 1
0 1 0
0 0 1
1 0 0
bsxfun(#eq, a', b)