# Defining commutation relations with Flat functions

Here is a minimal example of the problem I am having.

f[a___, b_, c_, d___] /; Not@OrderedQ[{b, c}] := h[b,c]f[a, c, b, d]
f[b, a, B, c, A]
SetAttributes[g, Flat]
g[a___, b_, c_, d___] /; Not@OrderedQ[{b, c}] := h[b,c]g[a, c, b, d]
g[b, a, B, c, A]


The f function works great. The g function goes into an infinite loop. How can I work around this problem? Perhaps an alternative to the Flat attribute or some other way of defining the commutation relation?

By the way, I set the attribute Flat because G[b, a, B, c, A] is often built up as follows:

SetAttributes[G, Flat]
G[b, G[G[a, B, c], A]]


Thanks to @alephalpha for explaining what the problem is and suggesting the following fix. EDIT: Actually the implementation below still runs an infinite loop on the second test cases below, independent of the order of definitions. EDIT: found a fix for that loop.

(* Flatten g instead of declaring Flat attribute *)
(* The next line was a failed attempt and gets overwritten *)
g[a___, b_g, c___] := Flatten[g[a, b, c]]
(* This line works *)
g[a___, b_g, c___] := Module[{temp},
temp = Flatten[Hold@g[a, b, c], \[Infinity], g] // Release]
g[a___, b_, c_, d___] /; Not@OrderedQ[{b, c}] := h[b, c] g[a, c, b, d]
g[b, a, B, c, A]
g[b, g[g[a, B, c], A]]


I am not sure how this will affect the pattern matching of other definitions, so I will leave the question open to see what others come up with and possibly get a discussion of the pros and cons of Flat vs Flatten.

This is a problem of pattern-matching.

When Mathematica evalutes the expression g[b, a, B, c, A], it attempts to apply any transformation rules for g. Here the transformation rule is:

g[a___, b_, c_, d___] /; Not@OrderedQ[{b, c}] :> h[b, c] g[a, c, b, d]


So Mathematica will find out the pattern that match g[a___, b_, c_, d___] /; Not@OrderedQ[{b, c}]. But g has the attribute Flat, so g[b, a, B, c, A] is the same as g[g[b], g[a], B, c, A]. So the first pattern Mathematica finds to match the pattern is g[g[b], g[a], B, c, A]. So it gets:

h[g[b], g[a]]g[g[a], g[b], B, c, A]


Of course, it is the same as:

h[g[b], g[a]] g[a, b, B, c, A]


Then Mathematica continues to evaluate g[a, b, B, c, A], which is the same as g[g[a, b], g[B], c, A]. OrderedQ[{g[a, b], g[B]}] returns False because g[a,b] has two arguments while g[B] has one. So it gets:

h[g[b], g[a]] h[g[a, b], g[B]] g[g[B], g[a, b], c, A]


which is the same as:

h[g[b], g[a]] h[g[a, b], g[B]] g[B, a, b, c, A]


Then Mathematica evaluates g[B, a, b, c, A] and gets:

h[g[b], g[a]] h[g[a, b], g[B]] h[g[a], g[B]] g[a, B, b, c, A]


But g[a, B, b, c, A] is the same as g[g[a, B], g[b], c, A]. So it gets:

h[g[b], g[a]] h[g[a, b], g[B]] h[g[a], g[B]] h[g[a, B], g[b]] g[b, a, B, c, A]


So it goes into an infinite loop.

You can use

Flatten[G[b, G[G[a, B, c], A]]] /. G -> f

• I am not accustomed to Flatten anything other than List. Thanks for pointing it out. I updated the question to show my interpretation of your suggestion. Do you see any secondary effects coming from replacing the Flat attribute with the Flatten function? – Timothy Wofford Oct 21 '13 at 7:40