1
$\begingroup$

In the code below I have defined a symbol that multiplies two block-matrices (I can't use the builtin Dot since Dot assumes that the matrix coefficients commute):

Unprotect[Times]

Times[c_,mat[0]]:=mat[0]
Protect[Times]
Unprotect[Plus]
Plus[m_,mat[0]]:=m
Plus[mat[0],m_]:=m
Protect[Plus]
SetAttributes[dot,{Flat,OneIdentity}]
dot[m_]:=m
dot[a___,mat[0],b___]:=mat[0]
dot[a_,mat[id]]:=a
dot[mat[id],a_]:=a
dot[m1___,c_*m_mat,m2___]:=c*dot[m1,m,m2]
dot[m1___,m2_+m3_,m4___]:=dot[m1,m2,m4]+dot[m1,m3,m4]
dot[m1_,m2_]/;(MatrixQ[m1]&&MatrixQ[m2]&&(Length[First[m1]]==Length[m2])) := 
  Table[
    Table[
      Apply[Plus,Table[dot[m1[[i,k]],m2[[k,j]]],{k,1,Length[m2]}]],
      {j,1,Length[First[m2]]}
    ],{i,1,Length[m1]}
  ]

As you can see I'm using the head mat to signal that a variable is a matrix, e.g. mat[0] is the zero matrix, mat[id] is the identity matrix and mat[a] is an indeterminant matrix with name a. The result of a test looks as follows: Test dot

So the computation works fine but why does Mathematica add Hold?

$\endgroup$
  • 3
    $\begingroup$ You will get a better response if you post the actual code rather than an image. $\endgroup$ – Simon Woods Jan 22 '15 at 13:34
  • 1
    $\begingroup$ Why don't you use UpValues rather than unprotecting Plus and Times? $\endgroup$ – Carlo Jan 22 '15 at 17:53
  • 2
    $\begingroup$ Just a small comment, you don't need to Unprotect Times or Plus. It is better if you do: mat /: Times[c_, mat[0]] := mat[0]. $\endgroup$ – FJRA Jan 22 '15 at 17:59
  • $\begingroup$ When I see a result like that, I make sure to pay attention to the warning messages that preceded it. I see no indication of those above. I don't suppose you thought they were optional? (I sometimes see people who treat stop signs that way, but that's a different matter.) $\endgroup$ – Daniel Lichtblau Jan 23 '15 at 15:53
  • $\begingroup$ "I can't use the built-in Dot since Dot assumes that the matrix coefficients commute…" - and that is why Mathematica provides Inner[], which you can then use with operators like NonCommutativeMultiply[] (**). $\endgroup$ – J. M. will be back soon May 29 '15 at 4:48
3
$\begingroup$

Although you did not provide copyable code for your final input if I run a rough facsimile I get an informative series of errors:

dot @@ Map[mat, RandomInteger[9, {2, 4, 4}], {3}]

$IterationLimit::itlim: Iteration limit of 4096 exceeded. >>

$IterationLimit::itlim: Iteration limit of 4096 exceeded. >>

$IterationLimit::itlim: Iteration limit of 4096 exceeded. >>

General::stop: Further output of $IterationLimit::itlim will be suppressed during this calculation. >>

Hold is inserted to prevent recursion (or iteration) from continuing when the output is printed.


A user wrote:

@Mr.Wizard: So Mathematica adds Hold to stop an infinite iteration. This answers my initial question but I still don't get why Mathematica gets stuck in an infinite loop. The Trace command reveals that Mathematica tries to apply the last definition over and over again. But according to the standard evaluation procedure it would have to stop once it determines that this definition is not applicable. Why does this not happen here?

I did not attempt to analyze your full code with modifications to System functions etc. However looking through the code I think I found the source of the problem. Please observe:

ClearAll[foo]
SetAttributes[foo, {Flat}]

foo[m_] := m

$IterationLimit = 20;

foo[{1, 2}, {3, 4}]

During evaluation of In[]:= $IterationLimit::itlim: Iteration limit of 20 exceeded. >>

Hold[foo[{1, 2}, {3, 4}]]

The solution is to change the order of your definitions to read:

ClearAll[dot]

dot[m_] := m

SetAttributes[dot, {Flat, OneIdentity}]

Please see these Q&A's for an explanation:

$\endgroup$

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.