# Pattern match with Table for matrix dimension check

In Mathematica, often an expression involving matrices will encounter dimension mismatch errors, like we are multiplying a 3x2 matrix to a 3x4 matrix. Below we define a new symbol Dim, which can be passed through your algorithm as a fake parameter to detect errors.

Dim /: Dot[Dim[{x_, y_}], z_] /;
MatrixQ[z] :=
(checkEq[y, Dimensions[z][]];
Dim[{x, Dimensions[z][]}]);


This method can handle most matrix operations, but failed on Table, which seems quite special. In fact, I failed to pattern match with Table by writing:

Dim /: Times[Dim[{x_, y_}], Table[z_]] := Dim[x, y];(*incorrect, just for syntax*)
Dim /: Times[Table[z_], Dim[{x_, y_}]] := Dim[x, y];


The expected result should be:

Dim[{3, 2}] Table[Sin[i + j], {i, 3}, {j, 2}] == Dim[{3, 2}]


But now Dim is multiplied over every element of table and it returns:

{{Dim[{3, 2}] Sin, Dim[{3, 2}] Sin}, {Dim[{3, 2}] Sin, Dim[{3, 2}] Sin}, {Dim[{3, 2}] Sin, Dim[{3, 2}] Sin}} == Dim[{3, 2}]


Full code:

Clear[Dim];
checkEq =
Function[{x, y},
If[x != y, Print[ToString[x] <> "!=" <> ToString[y]]; Abort[]]];
Dim /: Dimensions[Dim[x_]] := x;
Dim /: MatrixQ[Dim[_]] := True;
Dim /: Dot[Dim[{x_, y_}], z_] /;
MatrixQ[z] :=
(checkEq[y, Dimensions[z][]];
Dim[{x, Dimensions[z][]}]);
Dim /: Dot[z_, Dim[{x_, y_}]] /;
MatrixQ[z] :=
(checkEq[Dimensions[z][], x];
Dim[{Dimensions[z][], y}]);
Dim /: Times[z_, Dim[{x_, y_}]] /;
MatrixQ[z] :=
(checkEq[Dimensions[z], {x, y}]; Dim[{x, y}]);
Dim /: Times[Dim[{x_, y_}], z_] /;
MatrixQ[z] :=
(checkEq[Dimensions[z], {x, y}]; Dim[{x, y}]);
Dim /: Plus[z_, Dim[{x_, y_}]] /;
MatrixQ[z] :=
(checkEq[Dimensions[z], {x, y}]; Dim[{x, y}]);
(*Dim/:Dot[Dim[{x_,y_}],Dim[{z_,w_}]]:=(checkEq[y,z];Dim[{x,w}]);
Dim/:Times[Dim[{x_,y_}],Dim[{z_,w_}]]:=(checkEq[x,z];checkEq[y,w];Dim[{x,y}]);\
Dim/:Plus[Dim[{x_,y_}],Dim[{z_,w_}]]:=(checkEq[x,z];checkEq[y,w];Dim[{x,y}]);*)
Dim /: Times[x_, Dim[{y_, z_}]] /; NumberQ[x] := Dim[{y, z}];

(*Below are tests that should return true.*)
MatrixQ[Dim[{2, 3}]]
Dimensions@Dim[{1, 2}] == {1, 2}
Dim[{3, 2}].Dim[{2, 4}] == Dim[{3, 4}]
Dim[{3, 2}].RandomReal[1, {2, 4}] == Dim[{3, 4}]
RandomReal[1, {2, 4}].Dim[{4, 3}] == Dim[{2, 3}]
Dim[{3, 2}] Dim[{3, 2}] == Dim[{3, 2}]
2 Dim[{3, 2}] == Dim[{3, 2}]
Dim[{3, 2}] - Dim[{3, 2}] == Dim[{3, 2}]

(*Below are tests that should raise errors.*)
Dim[{3, 2}] - Dim[{2, 4}]
Dim[{3, 2}] Dim[{2, 4}]
Dim[{5, 3}].Dim[{2, 4}]

• I'm not sure I understand what underlying problem you're trying to solve here, let alone why this particular approach is being used... That said, Table[z_] expressions in code seem to be where your problem is... If you're trying to match a 'list of lists' that can be done; if you're trying to match an expression with the Head 'Table', that too can be done, although evaluation control will probably be needed. Advice: do some prototyping with MatchQ. This will force you to make explicit what you're trying to match, and will enable you to identify what will work. May 27, 2013 at 21:59

I believe you have an evaluation order problem. I suspect that you are unaware of the order of evaluation regarding UpValues definitions. Allow me to give a few illustrations.

I'll make a generic UpValue rule using UpSetDelayed:

_[___, up, ___] ^:= "one"


Arguments are evaluated before UpValues rules are triggered, unless the function has a Hold attribute such as HoldAll:

List[Print[1 + 1], up, Print[2 + 2]]


2

4

"one"


For this reason your Table is evaluated before your Dim rule is checked. Perhaps the most direct way around this is to use Unevaluated for every instance of Table. Using a simplified rule:

dim /: Times[dim[], _Table] := "Table found"

Times[dim[], Table[x[n], {n, 5}]] (* this doesn't match *)

{dim[] x, dim[] x, dim[] x, dim[] x, dim[] x}

Times[dim[], Unevaluated @ Table[x[n], {n, 5}]] (* this does *)

"Table found"


Of course this isn't very convenient.

I must admit I don't understand how you are intending to use Dims and why you don't merely check the data with Dimensions. If you explain that perhaps I can suggest a different implementation.

• +1, for taking the time to figure out something helpful to say. Jun 8, 2013 at 18:06