Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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][[1]]];
   Dim[{x, Dimensions[z][[2]]}]);

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[2], Dim[{3, 2}] Sin[3]}, {Dim[{3, 2}] Sin[3], Dim[{3, 2}] Sin[4]}, {Dim[{3, 2}] Sin[4], Dim[{3, 2}] Sin[5]}} == 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][[1]]];
   Dim[{x, Dimensions[z][[2]]}]);
Dim /: Dot[z_, Dim[{x_, y_}]] /;
   MatrixQ[z] :=
  (checkEq[Dimensions[z][[2]], x];
   Dim[{Dimensions[z][[1]], 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}]
share|improve this question
    
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. –  telefunkenvf14 May 27 '13 at 21:59

1 Answer 1

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[1], ___] ^:= "one"

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

List[Print[1 + 1], up[1], 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[1], dim[] x[2], dim[] x[3], dim[] x[4], dim[] x[5]}
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.

share|improve this answer
    
+1, for taking the time to figure out something helpful to say. –  Michael E2 Jun 8 '13 at 18:06

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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