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?
Answer
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]]]
Update
Jacob is asking how to preserve some of the evaluation rules of Times
, such as 0*x
→ 0
and 1*x
→ x
, 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]]
]
Comments
Post a Comment