Create matrix with N-4 rows and N-2 columns - matlab

Would you give me any comments on this question? I need to create a matrix in Matlab, following the description below:
for a given N and three values a, b and c. I want to create a (N-4)x(N-2) matrix, e.g. for N=8
a b c 0 0 0
0 a b c 0 0
0 0 a b c 0
0 0 0 a b c
Thanks a Lot

What you are trying to create is a toeplitz matrix. One you know the name, it's simple.
%construct the first row
row=zeros(N-2,1);
row(1:3)=[a,b,c];
%construct the first column
col=zeros(N-4,1);
col(1)=a;
%call the function
toeplitz(col,row)
Result with a=4;b=2;c=3;N=8;
ans =
4 2 3 0 0 0
0 4 2 3 0 0
0 0 4 2 3 0
0 0 0 4 2 3

You could solve using the identity matrix function eye() and some matrix concatenation:
N = 8;
a = 1;
b = 2;
c = 3;
a_I = [zeros(N-4, 0), a*eye(N-4), zeros(N-4, 2)];
b_I = [zeros(N-4, 1), b*eye(N-4), zeros(N-4, 1)];
c_I = [zeros(N-4, 2), c*eye(N-4), zeros(N-4, 0)];
X = a_I + b_I + c_I
Which produces the output
X =
1 2 3 0 0 0
0 1 2 3 0 0
0 0 1 2 3 0
0 0 0 1 2 3
You can also make it slightly more general and let the scalars a, b and c be contained in a vector:
N = 8;
v = [1 2 3];
X = zeros(N-4, N-2);
for ii = 1:length(v)
X = X + [zeros(N-4, ii-1), v(ii)*eye(N-4), zeros(N-4, length(v)-ii)];
end
Which produces the same output.

try this fully vectorized function:
function b=bandmat(a, N, M)
% license: CC-BY
% example: bandmat([1,2,3],4,6)
b=a(:).';
b(M+1)=0;
b=repmat(b,1,N);
b=reshape(b(1:end-N),M,N).';

Related

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))

Check neighbour pixels Matlab

I have a A which is 640x1 cell. where the value of each cell A(i,1) varies from row to row, for example A(1,1) =[], while A(2,1)=[1] and A(3,1)=[1,2,3].
There is another matrix B of size 480x640, where the row_index (i) of vector A corresponds to the col_index of matrix B. While the cell value of each row in vector A corresponds to the row_index in matrix B. For example, A(2,1)=[1] this means col_2 row_1 in matrix B, while A(3,1)=[1,2,3] means col_3 rows 1,2&3 in matrix B.
What I'm trying to do is to for each non-zero value in matrix B that are referenced from vector A, I want to check whether there are at least 4 other neighbors that are also referenced from vector A. The number neighbors of each value are determined by a value N.
For example, this is a part of matrix B where all the zeros"just to clarify, as in fact they may be non-zeros" are the neighbors of pixel X when N=3:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 X 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
As shown, because N=3, all these zeros are pixel X's neighbors. So if more than 4 neighbor pixels are found in vector A then do something e.g G=1 if not then G=0;
So if anyone could please advise. And please let me know if any more clarification is needed.
The first thing I would do is to convert your cell of indices A to a logic matrix Amat. This makes it easier to check how many neighbours are included in A.
Here is a solution that uses this conversion. I hope the comments are enough to make it understandable.
clear all
clc
nCols = 7;
nRows = 6;
N = 3; %// Number of neighbours
M = 4; %// Minimum number of wanted connections
%// Create cell of indices A
A = cell(nCols,1);
A{1} = [];
A{2} = 1;
A{3} = [1 2 3];
A{4} = [2 5];
A{5} = 3;
A{6} = [3 5];
A{7} = [1 4 6];
%// Generate radom data B
%// (There is a 50% probability for each element of B to be zero)
Bmax = 17;
B = (randi(2,nRows,nCols)-1).*(randi(Bmax,nRows,nCols));
%// Convert the cell A to a logic matrix Amat
Amat = zeros(size(B));
for ii = 1:nCols
Amat(A{ii},ii) = 1;
end
A
B
Amat
for ii = 1:nCols
for jj = A{ii}
if B(jj,ii)>0
%// Calculate neighbour indices with a lower bound of 1
%// and an upper bound of nCols or nRows
col_lim_low = max(1,ii-N);
col_lim_high = min(nCols,ii+N);
row_lim_low = max(1,jj-N);
row_lim_high = min(nRows,jj+N);
%// Get the corresponding neighbouring-matrix from Amat
A_neighbours = ...
Amat(row_lim_low:row_lim_high,col_lim_low:col_lim_high);
%// Check the number of neighbours against the wanted number M
if sum(A_neighbours(:)) > 1 + M
%# do something
fprintf('We should do something here at (%d,%d)\n',jj,ii)
end
end
end
end
The following is a printout from one run of the code.
A =
[]
[ 1]
[1x3 double]
[1x2 double]
[ 3]
[1x2 double]
[1x3 double]
B =
1 5 0 0 11 0 16
0 13 13 0 0 0 9
0 0 0 5 0 0 0
3 8 16 16 0 2 12
0 0 5 0 9 9 0
12 13 0 6 0 15 0
Amat =
0 1 1 0 0 0 1
0 0 1 1 0 0 0
0 0 1 0 1 1 0
0 0 0 0 0 0 1
0 0 0 1 0 1 0
0 0 0 0 0 0 1
We should do something here at (1,2)
We should do something here at (2,3)
We should do something here at (5,6)
We should do something here at (4,7)
Since you have a one-to-one correspondence between A and B, there is no need to work on A. B is a logical matrix (0 if not referenced in A, 1 if referenced). You can therefore apply a simple filter2 function counting the number of active neighbors within the 8 closest elements.
Here is the code
B = rand(10,10); %generate binary matrix
h = [1 1 1;1 0 1;1 1 1]; %filter to be applied
filter2(h,B,'same')>=4 & B>0 %apply filter on B, count minimum of 4 neighbors, if only B>1
EDIT
To transform a cell array B into binary presence (0=empty, 1=not empty), use of cellfunis straightforward
B = ~cellfun(#isempty,B);
And see Armo's response to your previous question for how to create B based on A.

Permute elements within rows of matrix

I have a matrix A
A = [0 0 0 0 1; 0 0 0 0 2; 0 1 2 3 4];
and I would like to randomly permute the elements within each row. For example, matrix A2
A2 = [1 0 0 0 0; 0 0 0 2 0; 4 1 3 2 0]; % example of desired output
I can do this with a vector:
Av = [0 1 2 3 4];
Bv = Av(randperm(5));
But I am unsure how to do this a row at time for a matrix and to only permute the elements within a given row. Is this possible to do? I could construct a matrix from many permuted vectors, but I would prefer not to do it this way.
Thanks.
You can use sort on a random array of any size (which is what randperm does). After that, all you need to do is some index-trickery to properly reshuffle the array
A = [0 0 0 0 1; 0 0 0 0 2; 0 1 2 3 4];
[nRows,nCols] = size(A);
[~,idx] = sort(rand(nRows,nCols),2);
%# convert column indices into linear indices
idx = (idx-1)*nRows + ndgrid(1:nRows,1:nCols);
%# rearrange A
B = A;
B(:) = B(idx)
B =
0 0 1 0 0
0 2 0 0 0
2 1 3 4 0

MATLAB - Add Value at the first column of a matrix

I want to add one value at the beginning of a matrix for example, my matrix is
0,0,0,0,0,0
0,1,1,1,0,0
1,0,0,1,0,0
1,1,1,0,0,0
then I want to add '1' or '0' at the first column therefore it will become like this
1,0,0,0,0,0,0
1,0,1,1,1,0,0
1,1,0,0,1,0,0
1,1,1,1,0,0,0
0,0,0,0,0,0,0
0,0,1,1,1,0,0
0,1,0,0,1,0,0
0,1,1,1,0,0,0
how can I do that in MATLAB?
You can concatenate matrices without creating another one from scratch like this:
% your matrix
A = [ 0,0,0,0,0,0;
0,1,1,1,0,0;
1,0,0,1,0,0;
1,1,1,0,0,0 ];
A_with_zeros = [zeros(size(A,1),1) A]
A_with_ones = [ones(size(A,1),1) A]
% Output:
% A_with_zeros = [ 0 0 0 0 0 0 0
% 0 0 1 1 1 0 0
% 0 1 0 0 1 0 0
% 0 1 1 1 0 0 0 ]
%
% A_with_ones = [ 1 0 0 0 0 0 0 0
% 1 0 0 1 1 1 0 0
% 1 0 1 0 0 1 0 0
% 1 0 1 1 1 0 0 0 ]
Documentation about concatenating matrices:
horzcat
vertcat
These two documentation pages describe in details the existing methods that let you concatenate arrays horizontally (what I did in the example above) and vertically (if you wanted to add lines to your matrix).
Use the array concatenation syntax - [a b] to glue matrices together horizontally, [a; b] to glue them together vertically.
Like so:
>> a = ones(3,1)
a =
1
1
1
>> b = magic(3)
b =
8 1 6
3 5 7
4 9 2
>> c = [a b]
c =
1 8 1 6
1 3 5 7
1 4 9 2
Vertically:
>> d = ones(1,3)
d =
1 1 1
>> e = [d; b]
e =
1 1 1
8 1 6
3 5 7
4 9 2
If you mismatch the dimensions, MATLAB will give you an error. Don't do this:
>> f = ones(1,10)
f =
1 1 1 1 1 1 1 1 1 1
>> g = magic(3)
g =
8 1 6
3 5 7
4 9 2
>> [f; g]
??? Error using ==> vertcat
CAT arguments dimensions are not consistent.
Create a new matrix with an extra column, copy the old matrix in, then put the data for the new column in at (:, 1).
output = zeros(size(input, 1), size(input, 2) + 1);
output(:, 2:end) = input;
output(:, 1) = new_column;
or if you mean that you want to get two matricies, one with a column of 1s and one with a column of 0s:
output0 = zeros(size(input, 1), size(input, 2) + 1);
output0(:, 2:end) = input;
output1 = ones(size(input, 1), size(input, 2) + 1);
output1(:, 2:end) = input;