0

I have a 102-by-102 matrix. I want to select square sub-matrices of orders from 2 up to 8 using random column numbers. Here is what I have done so far.

matt is the the original matrix of size 102-by-102.

ittr = 30
cols = 3;
for i = 1:ittr
   rr = randi([2,102], cols,1);
   mattsub = matt([rr(1) rr(2) rr(3)], [rr(1) rr(2) rr(3)]);
end

I have to extract matrices of different orders from 2 to 8. Using the above code I would have to change the mattsub line every time I change cols. I believe it is possible to do with another loop inside but cannot figure out how. How can I do this?

Adriaan
  • 17,741
  • 7
  • 42
  • 75
MathNovice
  • 35
  • 6
  • 2
    Can't you write `mattsub = matt(rr, rr);` ? – rahnema1 Feb 12 '18 at 20:34
  • what is the purpose of your loop? – Sardar Usama Feb 12 '18 at 20:42
  • It doesn't. The loop in your code does nothing other than overwriting `rr` and `mattsub` multiple times with random numbers. – Sardar Usama Feb 13 '18 at 08:58
  • You are very right. For the purpose of this question I didn't need the loop. Probably I have included it unintentionally because it is there in remaining code or may be I was thinking (as title says) the solution might involve another loop so how to handle both together? – MathNovice Feb 13 '18 at 09:18

3 Answers3

0

You don't need another loop, one is enough. If you use randi to get a random integer as size of your submatrix, and then use those to get random column and row indices you can easily get a random submatrix. Do note that the ouput is a cell, as the submatrices won't all be of the same size.

N=102; % Or substitute with some size function
matt = rand(N); % Initial matrix, use your own
itr = 30; % Number of iterations
mattsub = cell(itr,1); % Cell for non-uniform output
for ii = 1:itr
    X = randi(7)+1; % Get random integer between 2 and 7
    colr = randi(N-X); % Random column
    rowr = randi(N-X); % random row
    mattsub{ii} = matt(rowr:(rowr+X-1),colr:(colr+X-1));
end
Adriaan
  • 17,741
  • 7
  • 42
  • 75
0

Defining a set of random sizes is pretty easy using the randi function. Once this is done, they can be projected along your iterations number N using arrayfun. Within the iterations, the randperm and sort functions can be used in order to build the random indexers to the original matrix M.

Here is the full code:

% Define the starting parameters...
M = rand(102);
N = 30;

% Retrieve the matrix rows and columns...
M_rows = size(M,1);
M_cols = size(M,2);

% Create a vector of random sizes between 2 and 8...
sizes = randi(7,N,1) + 1;

% Generate the random submatrices and insert them into a vector of cells...
subs = arrayfun(@(x)M(sort(randperm(M_rows,x)),sort(randperm(M_cols,x))),sizes,'UniformOutput',false);

This can work on any type of matrix, even non-squared ones.

Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98
0

There is no need to extract elements of a vector and concatenate them, just use the vector to index a matrix.

Instead of :

mattsub = matt([rr(1) rr(2) rr(3)], [rr(1) rr(2) rr(3)]);

Use this:

mattsub = matt(rr, rr);
rahnema1
  • 15,264
  • 3
  • 15
  • 27