Using your method, here's a way to repeatedly generate a random matrix until the matrix is invertible. First, turn your matrix generation into a function so it's easy to call from two places.
Edit: Remove generation of options
from genmat
since options
doesn't change unless n
or m
are changed. ConstantArray
is faster than Table
for making a list of 1s. These changes find solution matrices more quickly (see comments).
genmat[n_, m_] := Prepend[RandomChoice[options,n^m - 1],ConstantArray[1,n^m]]
Next, initialize options
. Do this once for new values of n
or m
.
n = 2; m = 3;
options =
Complement[
DeleteDuplicates[
Table[Table[
Product[Tuples[Table[Tuples[{1, -1}, n], {m}]][[i]][[k]][[
Tuples[Table[i, {i, 1, n}], m][[j]][[k]]]], {k, 1, m}], {j,
1, Length[Tuples[Table[i, {i, 1, n}], m]]}],
{i, 1, Length[Tuples[Table[Tuples[{1, -1}, n], {m}]]]}]],
Union[Tuples[{1}, n^m], Tuples[{-1}, n^m]]];
The following While
command will run until the determinant of matarb
is not zero. Run again to find another matrix.
matarb = genmat[n, m]; (*initialize matrix*)
i = 0; (*counter*)
While[
Det[matarb] == 0, {matarb = genmat[n, m], i += 1}];
TableForm[{MatrixForm[matarb], Det[matarb], i},
TableDirections -> Row]
The result is a matrix, its determinant, and the number of matrices tested before finding a solution.
Eliminate singular matrices
Finding solution matrices is quicker if there are fewer singular cases to test. As Filburt says in his question, the options
matrix is symmetrical in this sense: the top half is the reverse of the negative of the bottom half. The symmetry is easy to see for the n=2, m=3 case:
choices = Length[options]/2 (*half the number of rows in the options matrix*);
TableForm[{MatrixPlot[Take[options, choices]],
MatrixPlot[Reverse[-Take[options, -choices]]]},
TableHeadings -> {{"Top half",
"Negative of bottom half,\nReversed"}}, TableDirections -> Row]

There are 17,297,280 possible test matrices using the original method where 14 rows of options
are randomly selected 7 rows at a time. More than 99% of them are singular.
To test symmetry for any n
and m
, simply:
Take[options,choices] == Reverse[-Take[options,-choices]]
True
- Case where n = 2, m = 3
Because the bottom half of options
is the negative of the top half, every corresponding row from the top half and the reverse of the bottom half of options
results in a singular matrix. For example, if a test run selects rows 1, 3, 5, and 7 from the top half, only rows 2, 4, 6 from the bottom half will not result in a singular matrix.
Because of the symmetry in the options
matrix, only the top half is needed.
cols = n^m;
top = Take[options, choices];
It's unnecessary to compute the bottom half of options
, because options == Join[top, Reverse[-top]]
.
We can entirely eliminate singular test matrices by randomly choosing rows from top
and the complement of the rows from -top
. Note that top
and -top
are not singular.
Here's how to make a list of random rows to be selected from top
:
tr = RandomSample[Range[1, choices], RandomInteger[choices]]
{6, 1, 5, 4}
Given tr
rows, these are the rows to select from -top
:
Complement[Range[choices], tr]
{2, 3, 7}
Then every random matarb
matrix is not singular (all singular test cases are eliminated):
tr = RandomSample[Range[1,choices], RandomInteger[choices]];
Det[matarb = Prepend[
Join[top[[tr, All]], -top[[Complement[Range[choices],tr]]]],
ConstantArray[1, cols]]]
The number of non-singular matrices (13,700 for n=2, m=3) is:
$$
\sum _{k=0}^{n^m-1} p\left(n^m-1,k\right)
$$
where $p({n},{k})\text{=}\frac{n!}{(n-k)!}$.
- Case where n = 2, m = any
Everything about the n=2, m=3 case applies when m
is any value. Every randomly chosen matrix is not singular.
- Case where n is not 2, m = any
When n
is not 2, the top and bottom halves of options
are symmetrical in the same way as the n=2 case. Test this as before with:
Take[options, choices] == Reverse[-Take[options, -choices]]
However, although choosing complementary rows reduces the number of singular test matrices, Monte Carlo testing is needed to eliminate the ones that remain. I haven't coded a way to exploit the symmetry in the options
matrix when n
is not 2, but the same complementary-rows technique will help. Meanwhile, this method using While
will find solutions.
choices = Length[options]/2;
cols = n^m;
matarb = Prepend[options[[RandomSample[Range[1,choices],cols-1], All]],
ConstantArray[1, cols]];
While[Det[matarb] == 0,
matarb = Prepend[
options[[RandomSample[Range[1,choices],cols-1], All]],
ConstantArray[1,cols]]];
Det[matarb]
RandomSample[...]
. Also your code is very difficult to follow with all the nested functions, you might consider refactoring it at least for the sake of getting more feedback. $\endgroup$RandomSample
answer the second question. I put the full setoptions
defined in the OP just to work exactly with the set I am interested in. But it could be another set o vectors from $\Bbb R^n$. I only want to find a way to repeat the action of generating a random matrix until it finds an invertible one. $\endgroup$options2=Table[Reverse[Sort[options]][[i]],{i,1,Length[options]/2}]
(which is identical tooptions2=Take[-options,Length[options]/2]
) eliminates half the valid solutions. See my new answer. I hope I clearly explained the symmetry inoptions
. $\endgroup$