Create a matrix with a diagonal and left-diagonal of all 1s in MATLAB - arrays

I would like to create a square matrix of size n x n where the diagonal elements as well as the left-diagonal are all equal to 1. The rest of the elements are equal to 0.
For example, this would be the expected result if the matrix was 5 x 5:
1 0 0 0 0
1 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 1
How could I do this in MATLAB?

Trivial using the tril function:
tril(ones(n),0) - tril(ones(n),-2)
And if you wanted a thicker line of 1s just adjust that -2:
n = 10;
m = 4;
tril(ones(n),0) - tril(ones(n),-m)
If you prefer to use diag like excaza suggested then try
diag(ones(n,1)) + diag(ones(n-1,1),-1)
but you can't control the 'thickness' of the stripe this way. However, for a thickness of 2, it might perform better. You'd have to test it though.

You can also use spdiags too to create that matrix:
n = 5;
v = ones(n,1);
d = full(spdiags([v v], [-1 0], n, n));
We get:
>> d
d =
1 0 0 0 0
1 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 1
The first two lines define the desired size of the matrix, assuming a square n x n as well as a vector of all ones that is of length n x 1. We then call spdiags to define where along the diagonal of this matrix this vector will be populating. We want to define the main diagonal to have all ones as well as the diagonal to the left of the main diagonal, or -1 away from the main diagonal. spdiags will adjust the total number of elements for the diagonal away from the main to compensate.
We also ensure that the output is of size n x n, but this matrix is actually sparse . We need to convert the matrix to full to complete the result.,

With a bit of indices juggling, you can also do this:
N = 5;
ind = repelem(1:N, 2); % [1 1 2 2 3 3 ... N N]
M = full(sparse(ind(2:end), ind(1:end-1), 1))

Simple approach using linear indexing:
n = 5;
M = eye(n);
M(2:n+1:end) = 1;

This can also be done with bsxfun:
n = 5; %// matrix size
d = [0 -1]; %// diagonals you want set to 1
M = double(ismember(bsxfun(#minus, 1:n, (1:n).'), d));
For example, to obtain a 5x5 matrix with the main diagonal and the two diagonals below set to 1, define n=5 and d = [0 -1 -2], which gives
M =
1 0 0 0 0
1 1 0 0 0
1 1 1 0 0
0 1 1 1 0
0 0 1 1 1

Related

MATLAB : Obtain a matrix by adding its last lines to the first lines of the basic matrix

I have a matrix B and I would like to obtain a new matrix C from B by adding its last w*a rows to the first w*a rows (w and a will be defined afterwards).
My matrix B is generally defined by :
I would like to obtain matrix C defined in a general way by:
The characteristics of matrices B and C are:
L and w are defined real values;
B0,B1,...,Bw are of dimension: a by b;
B is of dimension: [(L+w)×a] by (L×b);
C is of dimension: (L×a) by (L×b).
Example: For L = 4 and w = 2 I obtain the following matrix B:
The w*a = 2*1 = 2 last rows of B are:
The w*a = 2*1 = 2 first rows of B are:
By adding the two matrices we have:
The matrix C thus obtained is then:
For B0 = [1 0], B1 = [0 1] and B2 = [1 1]. We obtain :
B0, B1 and B2 are of dimension a by b i.e. 1 by 2;
B is of dimension: [(L+w )×(a)] by (L×b) i.e. [(4+2)×1] by (4×2) i.e. 6 by 8;
C is of dimension: (L×a) by (L×b) i.e. (4×1) by (4×2) i.e. 4 by 8.
The matrices B and C that I get are as follows:
B =
1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0
1 1 0 1 1 0 0 0
0 0 1 1 0 1 1 0
0 0 0 0 1 1 0 1
0 0 0 0 0 0 1 1
C =
1 0 0 0 1 1 0 1
0 1 1 0 0 0 1 1
1 1 0 1 1 0 0 0
0 0 1 1 0 1 1 0
I would like to have some suggestions on how to program this construction so that from a given matrix B I can deduce the matrix C.
Matlab's range indexing should help you do this in a few steps. The key things to remember are that ranges are inclusive, i.e. A[1:3] is a three 3x1 matrix, and that you can use the keyword end to automatically index the end of the matrix row or column.
%% Variables from OP example
w = 2;
L = 4;
B0 = [1 0];
B1 = [0 1];
B2 = [1 1];
[a, b] = size(B0);
% Construct B
BX = [B0;B1;B2]
B = zeros((L+w)*a, L*b);
for ii = 0:L-1
B(ii+1:ii+w+1, ii*b+1:ii*b+b) = BX;
end
%% Construct C <- THIS PART IS THE ANSWER TO THE QUESTION
% Grab first rows of B
B_first = B(1:end-w*a, :) % Indexing starts at first row, continues to w*a rows before the end, and gets all columns
% Grab last rows of B
B_last = B(end-w*a+1:end, :); % Indexing starts at w*a rows before the end, continues to end. Plus one is needed to avoid off by one error.
% Initialize C to be the same as B_first
C = B_first;
% Add B_last to the first rows of C
C(1:w*a, :) = C(1:w*a, :) + B_last;
I get the output
C =
1 0 0 0 0 0 1 1 0 1
0 1 1 0 0 0 0 0 1 1
1 1 0 1 1 0 0 0 0 0
0 0 1 1 0 1 1 0 0 0
0 0 0 0 1 1 0 1 1 0

Matlab : Sliding window using a matrix

I need some information on how to program the sliding window of matrix.
I have a diagonal matrix B defined below by:
I would like to deduce from the given matrix B and the size of the window W the different matrix for t ranging from 1 to the size L of the matrix.
Note: Each window has the same width and height. And the window moves on the diagonal.
Example: We have a matrix with size 5 by 8 and the size of the window is 3 by 4 and moves on the diagonal. The matrix B of the example is:
My code:
% Sliding window matrix
B = [ 1 1 0 0 0 0 0 0
2 2 1 1 0 0 0 0
0 0 2 2 1 1 0 0
0 0 0 0 2 2 1 1
0 0 0 0 0 0 2 2]; % Matrix B
W = 4; % Size of the window wanted here is 4
n = size(B,2) - W + 1;
X = zeros(size(B,1),W*n);
k = W-1:-1:0;
for i = 1:n
window = B(:,i:i+W-1)';
X(:,i*W - k) = B(:,i:i+W-1);
end
window;
With W = 4 and n of the for loop set to 1 I get:
window = [1 2 0 0 0
1 2 0 0 0
0 1 2 0 0
0 1 2 0 0];
Whereas I should get:
window = [1 1 0 0
2 2 1 1
0 0 2 2];
With my code I don't get exactly the different sub-matrix obtained by sliding window.
I would like my program to be able, depending on the matrix B and the choice of dimensions of my window, to return the diagonal matrix representing the window and shift one step to also recover the next diagonal matrix which is identical to the previous one, and so on until the end.
Any suggestions?
You need to specify window dimensions separately. Try this:
B = [ 1 1 0 0 0 0 0 0
2 2 1 1 0 0 0 0
0 0 2 2 1 1 0 0
0 0 0 0 2 2 1 1
0 0 0 0 0 0 2 2];
[bh, bw] = size(B); % matrix size
wh = 3; % window height
ww = 4; % window width
sx = 2; % sliding step length along 2nd dim
sy = 1; % sliding step length along 1st dim
wx = 1:sx:(bw-ww+1); % window left
wy = 1:sy:(bh-wh+1); % window top
n = min(numel(wx), numel(wy)); % number of windows which fit in matrix
for ii = 1:n
X = B((1:wh)+wy(ii)-1, (1:ww)+wx(ii)-1)
end
Note that the sliding window, as it is described in your question, does not necessarily visit the entire matrix diagonal. Unless you calculate the sx and sy based on the dimensions of the matrix.
B = randi(3, [8 13])
[bh, bw] = size(B); % matrix size
wh = 3; % window height
ww = 4; % window width
sx = 3; % slideing step length along 2nd dim
sy = 1; % slideing step length along 1st dim

How to unfold a Matrix on Matlab?

I have a given matrix H and I would like to unfold (expand) it to find a matrix B by following the method below :
Let H be a matrix of dimension m × n. Let x = gcd (m,n)
The matrix H is cut in two parts.
The cutting pattern being such that :
The "diagonal cut" is made by alternately moving c = n/x units to the right (we move c units to the right several times).
We alternately move c-b = m/x units down (i.e. b = (n-m)/x) (we move b units down several times).
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix B.
Exemple : Let the matrix H of dimension m × n = 5 × 10 defined by :
1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1
Let's calculate x = gcd (m,n) = gcd (5,10) = 5,
Alternatively move to the right : c = n/x = 10/5 = 2,
Alternatively move down : b = (n-m)/x = (10-5)/5 = 1.
Diagonal cutting diagram : The matrix H is cut in two parts.
The cutting pattern is such that :
We move c = 2 units to the right several times c = 2 units to the right,
We repeatedly move c - b = 1 unit downwards.
We get :
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix :
Remark : In the matrices X, X1 and X2 the dashes are zeros.
The resulting matrix B is (L is factor) :
Any suggestions?
This can be done by creating a logical mask with the cutting pattern, and then element-wise multiplying the input by the mask and by its negation. Repeating by L can be done with blkdiag.
H = [1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1];
L = 2;
[m, n] = size(H);
x = gcd(m, n);
c = n / x;
b = (n-m)/x;
mask = repelem(tril(true(m/b)), b, c);
A = [H.*mask; H.*~mask];
A = repmat({A}, L, 1);
B = blkdiag(A{:});

Reverse process of a matrix expansion on Matlab

My program allows to multiply a given B matrix with a z factor with some characteristics listed below, to give an H matrix. I would like to have a programming idea to do the inverse of what I programmed. That is to say with a given H matrix find the value of the B matrix.
For example with a matrix B = [-1 -1 ; 1 0]
I get with my code a matrix :
H = [ 0 0 0 0 0 0 ;
0 0 0 0 0 0 ;
0 0 0 0 0 0 ;
0 1 0 1 0 0 ;
0 0 1 0 1 0 ;
1 0 0 0 0 1 ]
I would like to have from a code H the value of the matrix B.
To specify the matrix H from the matrix B, it is necessary that:
Each coefficient -1 is replaced by a null matrix of dimension z*z;
Each coefficient 0 is replaced by an identity matrix of dimension z*z;
Each coefficient 1,2,...,z-1 is replaced by a circulating permutation matrix of dimension z*z shifted by 1,2,...,z-1 position to the right.
From a matrix B and the expansion factors z , we construct an extended binary H matrix with n-k rows and n columns.
My code :
clear;
close all;
B = [-1 -1 ; 1 0];
z = 3;
H = zeros(size(B)*z);
Y = eye(z);
for X1 = 1:size(B,1)
for X2 = 1:size(B,2)
X3 = B(X1,X2);
if (X3 > -1)
X4 = circshift(Y,[0 X3]);
else
X4 = zeros(z);
end
Y1 = (X1-1)*z+1:X1*z;
Y2 = (X2-1)*z+1:X2*z;
H(Y1,Y2) = X4;
end
end
[M,N] = size(H);
Any suggestions?
Assuming that all of the input matrices are well-formed, you can determine the mapping based on the first row of each block. For example, the block mapping to 1:
0 1 0
0 0 1
1 0 0
has a 1 in column 2 of row 1. Similarly, a one in column 1 maps to 0, and column 3 maps to 2. No ones in the row maps to -1. So we just need to find the column containing the 1 in the first row.
Annoyingly, find returns null when it doesn't find a nonzero value rather than 0 (which is what we would want in this case). We can adjust to this by adding a value to the matrix row that is only 1 when all of the others are 0.
If you have the Image Processing Toolbox, you can use blockproc to handle the looping for you:
B = blockproc(H, [z z], #(A)find([~any(A.data(1,:)) A.data(1,:)])-2);
Otherwise, just loop over the blocks and apply the function to each one.

How to resize / expand a matrix by adding zeros?

How is it possible to expand a quadratic - let's say NxN - matrix to a bigger on like a (N+k)x(N+k) matrix?
It's really all about resizing the matrix and filling the missing rows/columns with zeros such that not dimension mismatch occurs.
No need to do it more difficult than it is. MATLAB automatically pads with zeros if you assign something to an element outside of the original size:
n = 4;
A = [1 2; 3 4];
A(n,n) = 0;
A =
1 2 0 0
3 4 0 0
0 0 0 0
0 0 0 0
you can add zeros to a matrix using padarray... For example:
A = [1 2; 3 4];
B = padarray(A,[2 2],'post')
B =
1 2 0 0
3 4 0 0
0 0 0 0
0 0 0 0
Or, if you don't have the image processing toolbox, you can use matrix indexing:
B = zeros(size(A)+k, class(A));
B(k:end-k+1,k:end-k+1) = A;

Resources