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$
3
  • $\begingroup$ You might want to replace Dot with Inner, where you can direct it to use NonCommutativeMultiply in place of Times. $\endgroup$ Jan 30, 2016 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, 2016 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$ Feb 1, 2016 at 15:16

1 Answer 1

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$
2
  • $\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, 2017 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, 2017 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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