4
$\begingroup$

This may be a very basic question, so apologies in advance, I'm a first-time Mathematica & StackExchange user!

I have a 7x3 matrix X with all rows being unique in a 2D-list format.

For example:

X={{1,0,0},{0,1,0},{0,0,1},{1,1,0},{1,0,1},{0,1,1},{1,1,1}}

I want to choose three of these rows from which to construct a new matrix called Y, then calculate the rank of Y using MatrixRank.

For example: Y={{1,0,0},{0,0,1},{1,0,1}} OR Y={{0,1,0},{0,0,1},{1,1,1}} OR Y = ...

What I really want to do is create a loop that chooses a different set of three rows each time, and calculates the rank each time, until I find a set of three rows where the rank of my matrix Y is some arbitrary value z.

Finally, I want the loop to finish and tell me which rows were used to create Y that gave a rank of z. Is this possible?

$\endgroup$
6
$\begingroup$

This is a slightly different approach from what you asked, but still produces the wanted result. I won't use a loop, while I will look for all the possible combination "at the same time" (it's not always convenient to use loops in Mathematica).

X = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {1, 0, 1}, {0, 1, 1}, {1, 1, 1}};

Generate all possible subsets of 3 rows:

subs = Subsets[X, {3}];

define a z value (for example 2):

z = 2;

Find all the combinations of rows that give Rank = 2

Select[subs, MatrixRank[#] == z &]

{{{1, 0, 0}, {0, 1, 0}, {1, 1, 0}}, {{1, 0, 0}, {0, 0, 1}, {1, 0, 1}}, {{1, 0, 0}, {0, 1, 1}, {1, 1, 1}}, {{0, 1, 0}, {0, 0, 1}, {0, 1, 1}}, {{0, 1, 0}, {1, 0, 1}, {1, 1, 1}}, {{0, 0, 1}, {1, 1, 0}, {1, 1, 1}}}

If you want the list of the rank of each subset:

MatrixRank /@ subs

{3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3}

$\endgroup$
  • $\begingroup$ Thanks for your answer, it works perfectly. However, I have another example where my matrix X is far larger (56x21), and I wish z to be 21. This approach causes an error as there is insufficient memory for Mathematica to create all the many thousands of subsets of size 21x21. Is there a way to work out the rank of each subset and then stop when you find one that is 21, or another workaround that will take less memory? Thank you! $\endgroup$ – PeteG Feb 14 at 10:23
  • $\begingroup$ You might need to manually write a table or for loop for that, or you might look into lazy lists: mathematica.stackexchange.com/questions/9554/… . I don't have time now for implementing this solution but I might try it at some point! $\endgroup$ – Fraccalo Feb 14 at 11:21
7
$\begingroup$

You can also use Minors to get all square sub-matrices of desired dimensions:

minors = Join @@ Minors[X, 3, Identity];
mr2minors = Select[MatrixRank@# == 2 &]@minors;

Row[MatrixForm /@ mr2minors] 

enter image description here

List all 3X3 minors and highlight the ones with rank 2:

Grid @ Partition[MatrixForm /@ minors /. 
   a : MatrixForm[Alternatives @@ mr2minors] :> Highlighted @ a, 7]

enter image description here

$\endgroup$
  • $\begingroup$ Similar to my comment above, this solution works really nicely. However, it runs into the same problems with memory when the matrix X, and the integer z get larger. Any ideas for a solution? Thanks again! $\endgroup$ – PeteG Feb 14 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.