I have been trying to do some oscillator algebra in Mathematica and having troubles with sorting and simplifying expressions. I am using the NCAlgebra package which helps to improve the properties of NonCommutativeMultiply in Mathematica. However I have to create a huge list of rules to replace terms using the algebra. This quickly becomes impractical since I get these enormous expressions and I have to sift through the terms to see what simplifies and add more rules.

I have been wondering if there is a way to write a sorting function that would take an elementary expression and change it to a list and then permute the elements of list to sort the expression. I am fairly new to Mathematica but I would eventually like to write a small package which would allow me to these kind of manipulations.

For example, I have terms like $a**b**c**a^\dagger$ where $a$, $b$, $c$, etc. commute with each other but $a**a^\dagger-a^\dagger**a =1$. So I would like to sort things such that all dagger operators are to the left and have Mathematica use the fact that $a$, $b$, $c$ commute to rewrite the expressions. Right now I am assigning rules for every type of term that appears in my calculation but the number of terms has become unmanageable.

  • $\begingroup$ Hello Karan, welcome to Mathematica.SE? Did you mean a**a(dagger)-a(dagger)**a =1? Note that you can also write $\LaTeX$, just surround your expression with dollar signs. $\endgroup$
    – Szabolcs
    Dec 11, 2012 at 0:53
  • $\begingroup$ I was just going to point out what Szabolcs said... I've changed it to $\LaTeX$, but do review the dagger term. $\endgroup$
    – rm -rf
    Dec 11, 2012 at 0:56
  • $\begingroup$ Thanks for the edit guys. I have corrected it and will remember to format things correctly in future. $\endgroup$
    – Bilentor
    Dec 11, 2012 at 1:12
  • $\begingroup$ Check section "Some noncommutative algebraic manipulation" from nb available here $\endgroup$ Dec 11, 2012 at 16:27

3 Answers 3


The trick here is to take control of the non-commuting operators, and to define your own set of rules. Use prod as the head of each operator product, where prod[x,y] represents x ** y, and you can then define rules for manipulating prod.

Define rules that move $a^\dagger$ to the left in an operator product.

prod[u___, a, ad, v___] := prod[u, ad, a, v] + prod[u, v];
prod[u___, x : b | c, ad, v___] := prod[u, ad, x, v];

then you can evaluate

prod[a, b, c, ad]

(* prod[b, c] + prod[ad, a, b, c] *)

Generalisations of this sort of trick should solve your problem.

  • $\begingroup$ @Karan Stephen's suggestion is good. Does $a^\dagger$, indeed commute with $b$ and $c$, though? $\endgroup$ Dec 11, 2012 at 2:22
  • $\begingroup$ @Mark Yes $a^\dagger$ does commute with $b$ and $c$. However there is $b^\dagger$ and $c^\dagger$ which doesn't commute with b and c respectively. $\endgroup$
    – Bilentor
    Dec 11, 2012 at 2:38
  • $\begingroup$ @Stephen That sounds like a good idea. I will try this. $\endgroup$
    – Bilentor
    Dec 11, 2012 at 2:38
  • $\begingroup$ A more general approach would be to define prod[u___, a[i_], ad[j_], v___] := prod[u, ad[j], a[i], v] + prod[u, comm[a[i], ad[j]], v]; and then to define particular rules for c-number commutators such as prod[u___, comm[a[2], ad[1]], v___] := comm[a[2], ad[1]] prod[u, v]; $\endgroup$ Dec 11, 2012 at 3:27
  • $\begingroup$ @Stephen I tried what you suggested but I ran into troubles. Here is what I did: Prod[x___, y___] := x ** y; Prod[a___, b_, c_, d___] := Prod[a, c, b, d] + Comm[b, c] Prod[a, d];Comm[a, $a^\dagger$] = 1; Comm[b, $b^\dagger$] = 1; Comm[a, b] = 0; Comm[$a^\dagger$, b] = 0; Comm[a, $b^\dagger$] = 0; Comm[$a^\dagger$, $b^\dagger$] = 0; Prod[a, b, $a^\dagger$]. However this gives some errors. Where am I making a mistake? $\endgroup$
    – Bilentor
    Dec 11, 2012 at 7:13

One possibility is to use FeynCalc:

[rolfm@localhost ~]$ math
Mathematica 9.0 for Linux x86 (64-bit)
Copyright 1988-2012 Wolfram Research, Inc.

In[1]:= FilePrint@"karan"                                                                                                                                                                                                                                                                    
If FeynCalc is not already installed, do:
Commutator[a, ad] = 1;
Commutator[b, bd] = 1;
Commutator[b, ad] = 0;
Commutator[a, bd] = 0;
Commutator[ad,bd] = 0;
Commutator[a,  b] = 0;
DotSimplify[ a.b.ad ] 

In[2]:= <<karan                                                                                                                                                                                                                                                                              
Loading FeynCalc from /home/rolfm/.Mathematica/Applications/HighEnergyPhysics
FeynCalc 8.2.0 Type ?FeynCalc for help or visit http://www.feyncalc.org/
$PrePrint is set to FeynCalcForm. Use FI and FC to change the display format.

Out[2]= b + ad . b . a
  • $\begingroup$ Thanks for directing me to the package. It does do the job pretty neatly but somehow it is taking a very long time to do the calculations. I have a lot of expressions and using the DotSimplify on them is taking too long. Is there any way I can speed things up. $\endgroup$
    – Bilentor
    Dec 11, 2012 at 18:51
  • $\begingroup$ Maybe. Can you send me a notebook with some large expressions? $\endgroup$ Dec 11, 2012 at 21:48

It would have helped if you have gives a simple example of what you want.

But you could always do something like

expr = a x^3 + b x^2 + c x + d
Apply[List, expr]
(*  {d, c*x, b*x^2, a*x^3}  *)

Now to sort it, use Sort and you can apply your sorting function, as described in help:

"Sort[list,p] applies the function p to pairs of elements in list to 
determine whether they are in order. The default function p is 

You can also use Permute using some permutation group.

If you give a small example of an input, and what you like to get as output it will help.

  • $\begingroup$ Thanks for the help. I have edited the question to include an example. I will try what you suggested. $\endgroup$
    – Bilentor
    Dec 11, 2012 at 0:41

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.