5
$\begingroup$

I have matrices with entries where the order of the entries is important. Unfortunately Mathematica resorts terms in products in a lexicographic order. For example,

A = {{a1, a2}, {a3, a4}};
B = {{b1, b2}, {b3, b4}};
Z = {{z1, z2}, {z3, z4}};

Z.B.A

    (* {{a1 (b1 z1 + b3 z2) + a3 (b2 z1 + b4 z2),
         a2 (b1 z1 + b3 z2) + a4 (b2 z1 + b4 z2)}, {a1 (b1 z3 + b3 z4) +
         a3 (b2 z3 + b4 z4),  a2 (b1 z3 + b3 z4) +  a4 (b2 z3 + b4 z4)}} *)

I would like that Mathematica keeps the order of the terms as they appear in the product, i.e.

(* z1 b1 a1 + ... *)

How can the lexicographic ordering be disabled?

$\endgroup$
  • $\begingroup$ You might want to replace Dot with Inner, where you can direct it to use NonCommutativeMultiply in place of Times. $\endgroup$ – Daniel Lichtblau Jan 30 '16 at 22:15
  • $\begingroup$ @DanielLichtblau Thanks! Unforturtunately, Mathematica keeps all the zeroes for matrices that contain zeroes if I use Inner and NonCommutativeMultiply. For example, A = {{a1, a2, 0}, {0, a3, a4}, {0, a3, a4}}; B = {{b1, 0, b2}, {b3, 0, b4}, {b3, 0, b4}}; Z = {{z1, 0, z2}, {0, z3, z4}, {0, z3, z4}}; becomes {{0 ** b3 + a1 ** b1 + a2 ** b3, 0 ** 0 + a1 ** 0 + a2 ** 0, 0 ** b4 + a1 ** b2 + a2 ** b4}, {0 ** b1 + a3 ** b3 + a4 ** b3, 0 ** 0 + a3 ** 0 + a4 ** 0, 0 ** b2 + a3 ** b4 + a4 ** b4}, {0 ** b1 + a3 ** b3 + a4 ** b3, 0 ** 0 + a3 ** 0 + a4 ** 0, 0 ** b2 + a3 ** b4 + a4 ** b4}} $\endgroup$ – jak Feb 1 '16 at 8:36
  • $\begingroup$ You might want to use a few replacement rules to handle pulling scalars out of noncommutative products. I am pretty sure there are some past threads on MSE that show how this might be done. $\endgroup$ – Daniel Lichtblau Feb 1 '16 at 15:16
8
$\begingroup$

This is related to the Orderless attribute of Times and Plus. These attributes could be removed permanently with some hacks, but that would break Mathematica.

If you only want to display the result in a certain way, but not do calculations with it, it may be safe to remove those attributes temporarily using Block.

Block[{Plus, Times}, With[{result = Z.B.A}, HoldForm[result]]]

Mathematica graphics


Update

Jacob is asking how to preserve some of the evaluation rules of Times, such as 0*x0 and 1*xx, while still removing the Orderless attribute. This is possible with Internal`InheritedBlock. It works like Block in that any modifications to the blocked symbols will be temporary, but it does not remove blocked symbol definitions at the start. Thus we can selectively remove the Orderless attribute.

This is an undocumented function, so the usual caveats apply: it may change behaviour in future versions, it may behave unexpectedly, and it may even crash your kernel (this one has never crashed my kernel, but other internal functions have).

Internal`InheritedBlock[{Plus, Times},
 Unprotect[Plus, Times];
 ClearAttributes[{Plus, Times}, Orderless];
 With[{result = Z.B.A}, HoldForm[result]]
]
$\endgroup$
  • $\begingroup$ regarding Block[{Plus, Times}, With[{result = Z.B.A}, HoldForm[result]]] ... why does work? Does this combination of Block, With and HoldForm somehow drop the attributes from symbols given as the first argument to Block? I don't understand why this would happen. $\endgroup$ – billc Aug 27 '17 at 23:30
  • $\begingroup$ @billc "Does this ... somehow drop the attributes from symbols given as the first argument to Block?" Yes, that is exactly what Block does. It temporarily removes any definitions associated with those symbols. See (559). $\endgroup$ – Szabolcs Aug 28 '17 at 8:31

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.