Finding if a matrix is square

I have a matrix which is constructed element by element through some iterations, and thus can be non-square. If it’s not square, then I want to make it square filling with 0. Is there a function to determine if a matrix is square?

I was thinking of something like this:

(* If determinant of matrix is possible, then fill with 0s, else do nothing. *)
If[Det[matrix]=Indeterminate,Fillwithzeros[matrix]]

I’m pretty sure Det[matrix] = Indeterminate is not a correct way to express my thoughts, so maybe you could help me out with my syntax or even suggest a better way to do it 😀

Thanks!

=================

1

 

What about Dimensions and some ArrayPad?
– Yves Klett
May 13 ’14 at 17:14

1

 

Compare Equal @@ Dimensions[{{0, 0}, {0, 0}}] and Equal @@ Dimensions[{{0, 0}, {0, 0}, {0, 0}}] 🙂
– Öskå
May 13 ’14 at 17:16

1

 

BTW: Det[matrix]=Indeterminate is trying to set the value of Det[matrix] equal to Indeterminate not test if it is. Testing if A equals B is written ==. However Indeterminate is a symbol so you need === in that case.
– Ymareth
May 13 ’14 at 17:27

1

 

@SaxoMikoMola and where would you like the fill the rectangle matrix?
– Öskå
May 13 ’14 at 17:40

2

 

In V10, there is/will be SquareMatrixQ
– Michael E2
May 13 ’14 at 18:08

=================

3 Answers
3

=================

If you are concerned about the case where you list of lists has unequal length sublists then you should first do MatrixQ:

MatrixQ[#] && MatchQ[ Dimensions[#] , {_ ..}] &@ RandomInteger[10,{3,3}]

True

or

MatrixQ[#] && Equal @@ Dimensions@# &@{{1, 2, 1}, {1, 4, 4}, {4, 5, 4}}

True

padding

Normal@SparseArray[#, ConstantArray[Max@Dimensions@#,2]] &@ RandomReal[1, {4, 2}]

Here is what I would propose, but it can probably be faster:

filling[mat_] := If[Equal @@ Dimensions@mat, mat,
If[Less @@ Dimensions@mat,
Join[mat, SparseArray[{}, {1, Max@Dimensions@mat}]],
PadRight[mat[[#]], Max@Dimensions@mat] & /@ Range@Max@Dimensions@mat]]

where the test on the matrix squareness¹ is not needed.

mat[m_, n_] := RandomInteger[{0, 10}, {m, n}]

Examples:

SeedRandom@10;
mat[3, 2] // MatrixForm

(10109786)\left(
\begin{array}{cc}
10 & 10 \\
9 & 7 \\
8 & 6 \\
\end{array}
\right)

SeedRandom@10;
filling[mat[3, 2]] // MatrixForm

(10100970860)\left(
\begin{array}{ccc}
10 & 10 & 0 \\
9 & 7 & 0 \\
8 & 6 & 0 \\
\end{array}
\right)

SeedRandom@2;
mat[2, 3] // MatrixForm

(845474)\left(
\begin{array}{ccc}
8 & 4 & 5 \\
4 & 7 & 4 \\
\end{array}
\right)

SeedRandom@2;
filling[mat[2, 3]] // MatrixForm

(845474000)\left(
\begin{array}{ccc}
8 & 4 & 5 \\
4 & 7 & 4 \\
0 & 0 & 0 \\
\end{array}
\right)

Timings:

filling[mat[10000, 9999]]; // AbsoluteTiming

{1.897158, Null}

filling[mat[9999, 10000]]; // AbsoluteTiming

{1.651018, Null}

filling[mat[10000, 10000]]; // AbsoluteTiming

{1.253314, Null}

The last being approximately equivalent to mat[10000, 10000]; // AbsoluteTiming

¹ squareQ = Equal @@ Dimensions@# &;

pad = With[{dim = Dimensions@#},
If[Equal @@ dim, #, ArrayPad[#, {{0, 0}, Abs[dim – Max@dim]}\[Transpose]]]] &;

pad @ RandomReal[1, {4, 2}] // MatrixForm

Edit this version is going to work with multidimensional matrices too 🙂

pad = With[{dim = Dimensions@#},
If[Equal @@ dim, #, ArrayPad[#, {0 dim, Abs[dim – Max@dim]}\[Transpose]]]] &;

pad @ RandomReal[1, {3, 2, 3, 2}] // MatrixForm

  

 

Damn, I was really wondering how to use ArrayPad, I guess I was missing the Abs[dim – Max@dim] part.. 🙂
– Öskå
May 13 ’14 at 19:21

  

 

@Öskå Thanks 😛 I was looking for more compact way but I’ve failed 🙁
– Kuba
May 13 ’14 at 19:23

  

 

It’s already quite compact compared to mine 😛 I feel stupid now for not handling ArrayPad 🙂
– Öskå
May 13 ’14 at 19:25

1

 

@Öskå now George made me stupid ;P
– Kuba
May 13 ’14 at 19:41