# How does SortOrder work?

I have the following indices:

{A,B,C,D,E,F,F#}::Indices(full).
{a,b,c,d,e,f,f#}::Indices(space1).
{m,n,o,p,q,r,r#}::Indices(space2).
\partial{#}::PartialDerivative.


And these fields: $\lambda_{AB}, F_{A}, F_{A B C}$ and their derivatives. I am using the versions of the fields with split indices (i.e. $a,b,c,..$ and $m,n,o..$).

I have a test expression

$$c_0\partial_{b m}F_{m a c}F_{c}\lambda_{a b}+\lambda_{c e}\partial_{e n}F_{n c b}F_{b}c_3+\lambda_{m n}\partial_{a a}F_{b c m}F_{b c n}c_1+\lambda_{c d}\partial_{n}F_{n c d}c_2$$

I want to use sort_product in such a way that first are the $\lambda$ expessions, then $F$ with one index, then $F$ with three indices, and then first derivatives then second and so on, all regardless of indices they have.

I declare a SortOrder line in the code. No matter what I put there it never works correcly, first I tried using the exact same indices as in the test expression and writing the order very explicitely:

{\lambda_{a b},\lambda_{m n},\lambda_{c e},F_{c},F_{b c n},\partial_{n}{F_{n c d}},\partial_{b m}{F_{m a c}},\partial_{e n}{F_{n c b}}}::SortOrder;


Then I tried using the question mark and hashtag operators, ideally I would want something like this:

{\lambda_{#},F_{#},\partial_{#}{#}}::SortOrder;


Which would exactly accomplish what I want if it worked. No matter what combination I tried it never worked perfectly sometimes it correctly shuffled one term but others would be in the wrong order. The actual expession I am working with in my codes has about a hundred terms.

I would like to ask what I should write so sort_product achieves the desired order?

+1 vote

There's two issues to keep in mind here:

1. The # pattern only really works to indicate 'an object with any number of child nodes, be it subscripts, superscripts or ordinary arguments'. In particular, it does not mean 'any number of elements' (at least not right now; I have some plans to add proper patterns for 'a range of symbols', but that is not active right now).
2. Assigning a SortOrder property to a list and then re-assigning one to a different list (like when you write one, find out it does not work, then write down a slight modification and re-executing that cell) is not going to automatically forget the previous one, unless you restart the kernel. For most properties that's what you want, but for SortOrder it's a bit annoying/confusing.

Anyway, a solution to your problem is:

{A,B,C,D,E,F,F#}::Indices(full).
{a,b,c,d,e,f,f#}::Indices(space1).
{m,n,o,p,q,r,r#}::Indices(space2).
\partial{#}::PartialDerivative.

ex:=c_{0} \partial_{b m}{F_{m a c}} F_{c} \lambda_{a b}
+ \lambda_{c e}\partial_{e n}{F_{n c b}} F_{b} c_{3}
+ \lambda_{m n}\partial_{a a}{F_{b c m}} F_{b c n} c_{1}
+ \lambda_{c d} \partial_{n}{F_{n c d}} c_{2};

{\lambda_{#}, F_{a?}, F_{a? b?}, F_{a? b? c?}, \partial_{a?}{A??}, \partial_{a? b?}{A??} }::SortOrder;

sort_product(ex);


which produces

$$\lambda_{a b} F_{c} \partial_{b m}{F_{m a c}} c_{0}+\lambda_{c e} F_{b} \partial_{e n}{F_{n c b}} c_{3}+\lambda_{m n} F_{b c n} \partial_{a a}{F_{b c m}} c_{1}+\lambda_{c d} \partial_{n}{F_{n c d}} c_{2}$$

I have used a? type wildcards for the indices to capture both the 'space1' and 'space2' set possibilities in one expression. The A?? stands for 'any object'.

Hope this helps.