Skip to content

Instantly share code, notes, and snippets.

@ellisonbg
Created May 15, 2014 22:24
Show Gist options
  • Save ellisonbg/c3aec217802a341631b5 to your computer and use it in GitHub Desktop.
Save ellisonbg/c3aec217802a341631b5 to your computer and use it in GitHub Desktop.
Creation Operators in SymPy
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"name": "",
"signature": "sha256:62c209a8a9cc3cb29ad4b2c605e4a036bca0f66d5bd1f9d187682fb6c027e5e2"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Creation Operators in SymPy"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from sympy.physics.quantum import *\n",
"from sympy import *\n",
"from sympy import init_printing"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 6
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"init_printing(use_latex='mathjax')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook is an attempt to understand the physics of the creation and anihilation operators in SymPy in a couple of different places:\n",
"\n",
"* `sympy.physics.quantum.sho1d`\n",
"* `sympy.physics.secondquant`\n",
"* This [PR](https://github.com/sympy/sympy/pull/2692) (`fieldoperator.py`)\n",
"\n",
"I begin with a short review of the algebraic properties of two types of creation and anihilation operators."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Single particle operators"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The single particle creation and anihilation operators $a$ and $a^\\dagger$ satisfy the following commutation relations:\n",
"\n",
"$$ [ a, a^\\dagger ] = 1 $$\n",
"$$ [a, a] = [a^\\dagger, a^\\dagger] = 0 $$\n",
"\n",
"These operators create single particle *excitations*. When they are applied to number states $|n\\rangle$ they stricly preserve particle number ($N=1$), but change the excitation number $n$. This is the physics of a single particle in different eigenstates.\n",
"\n",
"If $b$ and $b^\\dagger$ are another set of these single particle operators, they satisfy the same commutation relationships with each other:\n",
"\n",
"$$ [ b, b^\\dagger ] = 1 $$\n",
"$$ [b, b] = [b^\\dagger, b^\\dagger] = 0 $$\n",
"\n",
"However, because these operators create excitations rather than particles, the operators commute with each other always:\n",
"\n",
"$$ [a, b] = [a, b^\\dagger] = 0 $$\n",
"\n",
"At first glance these operators look like those of multiple identical bosons. However, when you look at the fermionic version of these operators, you see that is not the case.\n",
"\n",
"Let $c$ and $c^\\dagger$ satisfy the relations:\n",
"\n",
"$$ \\{c, c^\\dagger\\} = 1 $$\n",
"$$ \\{c, c\\} = 2c^2 $$\n",
"$$ \\{c^\\dagger, c^\\dagger\\} = 2(c^\\dagger)^2 $$\n",
"\n",
"And $d$ and $d^\\dagger$ also satisfy these relationships:\n",
"\n",
"$$ \\{d, d^\\dagger\\} = 1 $$\n",
"$$ \\{d, c\\} = 2d^2 $$\n",
"$$ \\{d^\\dagger, d^\\dagger\\} = 2(d^\\dagger)^2 $$\n",
"\n",
"The core question is this: what are the commutation/anticommutation relationships between $c$ and $d$? If these operators represented identical fermions, the answer would be:\n",
"\n",
"$$ \\{c,d\\} = \\{c,d^\\dagger\\} = \\{c^\\dagger, d\\} = 0 $$\n",
"\n",
"However, because these operators don't refer to particles, but rather excitations, they represent distinguishable systems and actually satisfy:\n",
"\n",
"$$ [c,d] = [c,d^\\dagger] = [c^\\dagger] = 0 $$\n",
"\n",
"Because of this simple fact, these operators cannot ever be used to describe multiple identical particles."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Multiple identical particles"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are another, similar set of operators that can be used to describe identical systems of bosons and fermions. The canonical reference for these operators is Fetter and Walecka's *Quantum Theory of Many Particle Systems*.\n",
"\n",
"Let $a_i^\\dagger$ and $a_i$ and be a set of creation and anihilation operators that create and destroy an identical boson in single particle state $i$. They satisfy the commutation relations:\n",
"\n",
"$$ [a_i, a_j^\\dagger] = \\delta_{ij} $$\n",
"$$ [a_i, a_j] = [a_i^\\dagger, a_j^\\dagger] = 0 $$\n",
"\n",
"Let the operators $b_i$ and $b_i^\\dagger$ describe a different set of identical bosons that are identical among themselves, but distinguishable from the particles described by $a_i$. Then:\n",
"\n",
"$$ [b_i, b_j^\\dagger] = \\delta_{ij} $$\n",
"$$ [b_i, b_j] = [b_i^\\dagger, b_j^\\dagger] = 0 $$\n",
"\n",
"And:\n",
"\n",
"$$ [a_i, b_j] = [a_i^\\dagger, b_j] = [a_i, b_j^\\dagger] = 0 $$\n",
"\n",
"Likewise, if $c_i$ and $d_j$ are operators for two distinguishable sets of identical fermions:\n",
"\n",
"$$ \\{c_i, c_j^\\dagger\\} = \\delta_{ij} $$\n",
"$$ \\{c_i, c_j\\} = \\{c_i^\\dagger, c_j^\\dagger\\} = 0 $$\n",
"\n",
"$$ \\{d_i, d_j^\\dagger\\} = \\delta_{ij} $$\n",
"$$ \\{d_i, d_j\\} = \\{d_i^\\dagger, d_j^\\dagger\\} = 0 $$\n",
"\n",
"$$ [c_i, d_j] = [c_i^\\dagger, d_j] = [c_i, d_j^\\dagger] = 0 $$\n",
"\n",
"Note that this last set of relations are *commutators* not anticommutators. This is because distinguishable particles are described by vanishing commutators."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"How are these two pictures related?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An interesting question is if the two different sets of operators can be related to one another. This type of relationship would be algebraic, rather than physical as their interpretation is completely different and incompatible. But let's try...\n",
"\n",
"Let's say we have a system of identical fermions where two states are possible:\n",
"\n"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"fieldoperator.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's look at how the operators in `fieldoperator.py` behave in this light."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from sympy.physics.quantum import fieldoperator as fo"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here is a single bosonic operator:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = fo.BosonOperator('a')\n",
"b = fo.BosonOperator('b')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"They clearly obey the single particle commutation relations:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(Commutator(a, Dagger(a)).doit())\n",
"display(Commutator(a, a).doit())\n",
"display(Commutator(Dagger(a), Dagger(a)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$1$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"1"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However, if you look at the commutators between the $a$ and $b$ operators, they don't know what to do. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(Commutator(a, b).doit())\n",
"display(Commutator(a, Dagger(b)).doit())\n",
"display(Commutator(Dagger(a), b).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$${a} {b} - {b} {a}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"BosonOperator(a,1)\u22c5BosonOperator(b,1) - BosonOperator(b,1)\u22c5BosonOperator(a,1)"
]
},
{
"latex": [
"$${a} {{b}^\\dagger} - {{b}^\\dagger} {a}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"BosonOperator(a,1)\u22c5BosonOperator(b,0) - BosonOperator(b,0)\u22c5BosonOperator(a,1)"
]
},
{
"latex": [
"$${{a}^\\dagger} {b} - {b} {{a}^\\dagger}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"BosonOperator(a,0)\u22c5BosonOperator(b,1) - BosonOperator(b,1)\u22c5BosonOperator(a,0)"
]
}
],
"prompt_number": 23
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A decision has to be made for these commutators. For bosons the answer is simple: they should all vanish. If this is done, these operators fully satisfy the requirements for the single particle operators. However, these operators would then also satisfy the multiparticle algebra with the mapping:\n",
"\n",
"$$ a \\rightarrow a_0 $$\n",
"$$ b \\rightarrow a_1 $$\n",
"$$ c \\rightarrow a_2 $$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's look at the fermionic operators"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"c = FermionOperator('c')\n",
"d = FermionOperator('d')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 26
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Again, these are clearly single particle operators:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(AntiCommutator(c, Dagger(c)).doit())\n",
"display(AntiCommutator(c, c).doit())\n",
"display(AntiCommutator(Dagger(c), Dagger(c)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$1$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"1"
]
},
{
"latex": [
"$$2 \\left({c}\\right)^{2}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
" 2\n",
"2\u22c5FermionOperator(c,1) "
]
},
{
"latex": [
"$$2 \\left({{c}^\\dagger}\\right)^{2}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
" 2\n",
"2\u22c5FermionOperator(c,0) "
]
}
],
"prompt_number": 27
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"However the anticommutators between $c$ and $d$ are not defined."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(AntiCommutator(c, d).doit())\n",
"display(AntiCommutator(c, Dagger(d)).doit())\n",
"display(AntiCommutator(Dagger(c), d).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$${c} {d} + {d} {c}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"FermionOperator(c,1)\u22c5FermionOperator(d,1) + FermionOperator(d,1)\u22c5FermionOperat\n",
"or(c,1)"
]
},
{
"latex": [
"$${c} {{d}^\\dagger} + {{d}^\\dagger} {c}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"FermionOperator(c,1)\u22c5FermionOperator(d,0) + FermionOperator(d,0)\u22c5FermionOperat\n",
"or(c,1)"
]
},
{
"latex": [
"$${{c}^\\dagger} {d} + {d} {{c}^\\dagger}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"FermionOperator(c,0)\u22c5FermionOperator(d,1) + FermionOperator(d,1)\u22c5FermionOperat\n",
"or(c,0)"
]
}
],
"prompt_number": 28
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"How should they be defined? Unlike the bosons there are two options in this case:\n",
"\n",
"1. The commutators of $c$ and $d$ should vanish. In this case, $c$ and $d$ define single particle operators.\n",
"2. The anticommutators of $c$ and $d$ should vanish. In this case, $c$ and $d$ define the identical particle operators for fermions with the mapping:\n",
"\n",
"$$ c \\rightarrow c_0 $$\n",
"$$ d \\rightarrow c_1 $$\n",
"$$ e \\rightarrow c_2 $$\n",
"\n",
"What is important is that these operators can't satisfy the algebra for both cases."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"secondquant.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's look at the commutation relations in `secondquant.py`."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from sympy.physics import secondquant as sq"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 43
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The first thing to notice is that the operator names/labels are hardcoded to the letter `b` for bosons. This means that `secondquant.py` is not capable of handling different sets of bosons that are identical among themselves, but distinguishable between different sets."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"bi = sq.AnnihilateBoson('i')\n",
"bj = sq.AnnihilateBoson('j')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 61
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(bi)\n",
"display(bj)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$b(i)$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"b(i)"
]
},
{
"latex": [
"$$b(j)$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"b(j)"
]
}
],
"prompt_number": 62
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These definitely behave like identical bosons:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(sq.Commutator(bi, sq.Dagger(bj)).doit())\n",
"display(sq.Commutator(bi, bj).doit())\n",
"display(sq.Commutator(sq.Dagger(bi), sq.Dagger(bj)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$\\delta_{i j}$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"\u03b4 \n",
" i,j"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
}
],
"prompt_number": 64
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"fi = sq.AnnihilateFermion('i')\n",
"fj = sq.AnnihilateFermion('j')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 57
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Aparently `secondquant.py` doesn't have an `AntiCommutator` defined."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(sq.AntiCommutator(fi, sq.Dagger(fj)).doit())\n",
"display(sq.AntiCommutator(fi, fj).doit())\n",
"display(sq.AntiCommutator(sq.Dagger(fi), sq.Dagger(fj)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'module' object has no attribute 'AntiCommutator'",
"output_type": "pyerr",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-65-519673044283>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAntiCommutator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDagger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdoit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAntiCommutator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdoit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mdisplay\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mAntiCommutator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDagger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDagger\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfj\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdoit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mAttributeError\u001b[0m: 'module' object has no attribute 'AntiCommutator'"
]
}
],
"prompt_number": 65
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"sho1d.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's look at how `sho1d.py` handles these things."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from sympy.physics.quantum import sho1d"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 35
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = sho1d.LoweringOp('a')\n",
"b = sho1d.LoweringOp('b')"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 36
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For the same label, the operators satisfy the single particle algebra:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(Commutator(a, Dagger(a)).doit())\n",
"display(Commutator(a, a).doit())\n",
"display(Commutator(Dagger(a), Dagger(a)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$1$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"1"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
},
{
"latex": [
"$$0$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"0"
]
}
],
"prompt_number": 41
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But for different labels, it is completely broken:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"display(Commutator(a, b).doit())\n",
"display(Commutator(Dagger(a), b).doit())\n",
"display(Commutator(a, Dagger(b)).doit())"
],
"language": "python",
"metadata": {},
"outputs": [
{
"latex": [
"$$a b - b a$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"a\u22c5b - b\u22c5a"
]
},
{
"latex": [
"$$-1$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"-1"
]
},
{
"latex": [
"$$1$$"
],
"metadata": {},
"output_type": "display_data",
"text": [
"1"
]
}
],
"prompt_number": 42
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Summary and recommendations"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* The `BosonOperators` with different names/labels should commute. This is a no brainer as it means these operators satisfy both algebras.\n",
"* All `BosonOperators` and `FermionOperators` should commute with each other. Again a no brainer, as they are distinguishable in all cases.\n",
"* For the `FermionOperator` case, we have to decide how to treat commutators/anticommutators of operators with different labels. There are two options: 1) commutators vanish or 2) anticommutators vanish. These two choices describe different physics. Whichis more relevant for the quantum optics usage cases?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment