I have a set of algebraic expressions of a certain form, and I would like to make them into Associations in a specified way. My expressions are formed of two heads, M and Plus, and then they may have any leaves at the bottom. The leaves are of the form of some specified head, for which I use e[_], times other numerical or symbolic algebraic factors. I want the Association to group together the sums of the sets of leaves with the signature of their associated permutation as they arise in the original expression. The signature of any expression with repeated leaves would be I will try to explain this by way of a couple of examples.

Example one:

M[e[1], M[a e[2], b e[4]] + M[6 e[3], e e[4]], -5 e[2]]

This looks like it would map to

<|M[e[1],e[2],e[2],e[4]] -> -5 a b, M[e[1],e[2],e[3],e[4]] -> -30 e|>

But actually we don't want any repeated leaves so we wouldn't pick up the first term, and we'd get

<|M[e[1],e[2],e[3],e[4]] -> -30 e|>

So we ordered the permutation of the leaves and kept this as the key, and picked out the numerical factors associated with each leaf along with the the signature of the permutation, and put these as the associated value.

Example two:

Another example which shows that each value could come from more than one individual term which get added together could be ;

M[e[1] + 2 e[2] - c e[3], e[1] + a e[4] - b e[2], e[1] + e[2] + e[3]]

Which would give association;

<| M[e[1], e[2], e[3]] -> (-2 - b - c - b c), M[e[1], e[2], e[4]]-> a  M[e[1], e[3], e[4]] -> (-a - a c), M[e[2], e[3], e[4]]-> (-2 a - a c)|>

I can also provide an explicit function which applies these rules to an expression of the form which I specify, and produces the association that I want. This is the following;

makeassoc[expr_] := Module[{tempexpr = Distribute[expr]},
  tempexpr = 
   tempexpr //. 
    M[a___, Times[y___, e[k_], z___], b___] :> y z M[a, e[k], b];

  tempexpr = tempexpr /. M[c___, x_, b___, x_, a___] -> 0;

  tempexpr = tempexpr /. M[x__] :> Signature[{x}] M @@ Sort[{x}];

  tempexpr = tempexpr // Collect[#, M[__]] &;

  tempexpr = 
   List @@ ( tempexpr /. Times[x__, M[y__], z___] :> M[y] -> x z) // 

The reason that I don't just use this function is down to efficiency. In doing the calculation this way, we must expand out all of the multiplications (the M head) which (for my real-use cases) results in very large internal expressions, before then constructing an association where most of the elements were zero, or grouped together. It should be much more efficient to only go through and pick up the terms that we need, using some sort of branching search type algorithm, but I don't know how to code this.

Thanks very much for any help.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.