290 lines
10 KiB
Python
290 lines
10 KiB
Python
"""Functions for reordering operator expressions."""
|
|
|
|
import warnings
|
|
|
|
from sympy.core.add import Add
|
|
from sympy.core.mul import Mul
|
|
from sympy.core.numbers import Integer
|
|
from sympy.core.power import Pow
|
|
from sympy.physics.quantum import Commutator, AntiCommutator
|
|
from sympy.physics.quantum.boson import BosonOp
|
|
from sympy.physics.quantum.fermion import FermionOp
|
|
|
|
__all__ = [
|
|
'normal_order',
|
|
'normal_ordered_form'
|
|
]
|
|
|
|
|
|
def _expand_powers(factors):
|
|
"""
|
|
Helper function for normal_ordered_form and normal_order: Expand a
|
|
power expression to a multiplication expression so that that the
|
|
expression can be handled by the normal ordering functions.
|
|
"""
|
|
|
|
new_factors = []
|
|
for factor in factors.args:
|
|
if (isinstance(factor, Pow)
|
|
and isinstance(factor.args[1], Integer)
|
|
and factor.args[1] > 0):
|
|
for n in range(factor.args[1]):
|
|
new_factors.append(factor.args[0])
|
|
else:
|
|
new_factors.append(factor)
|
|
|
|
return new_factors
|
|
|
|
def _normal_ordered_form_factor(product, independent=False, recursive_limit=10,
|
|
_recursive_depth=0):
|
|
"""
|
|
Helper function for normal_ordered_form_factor: Write multiplication
|
|
expression with bosonic or fermionic operators on normally ordered form,
|
|
using the bosonic and fermionic commutation relations. The resulting
|
|
operator expression is equivalent to the argument, but will in general be
|
|
a sum of operator products instead of a simple product.
|
|
"""
|
|
|
|
factors = _expand_powers(product)
|
|
|
|
new_factors = []
|
|
n = 0
|
|
while n < len(factors) - 1:
|
|
current, next = factors[n], factors[n + 1]
|
|
if any(not isinstance(f, (FermionOp, BosonOp)) for f in (current, next)):
|
|
new_factors.append(current)
|
|
n += 1
|
|
continue
|
|
|
|
key_1 = (current.is_annihilation, str(current.name))
|
|
key_2 = (next.is_annihilation, str(next.name))
|
|
|
|
if key_1 <= key_2:
|
|
new_factors.append(current)
|
|
n += 1
|
|
continue
|
|
|
|
n += 2
|
|
if current.is_annihilation and not next.is_annihilation:
|
|
if isinstance(current, BosonOp) and isinstance(next, BosonOp):
|
|
if current.args[0] != next.args[0]:
|
|
if independent:
|
|
c = 0
|
|
else:
|
|
c = Commutator(current, next)
|
|
new_factors.append(next * current + c)
|
|
else:
|
|
new_factors.append(next * current + 1)
|
|
elif isinstance(current, FermionOp) and isinstance(next, FermionOp):
|
|
if current.args[0] != next.args[0]:
|
|
if independent:
|
|
c = 0
|
|
else:
|
|
c = AntiCommutator(current, next)
|
|
new_factors.append(-next * current + c)
|
|
else:
|
|
new_factors.append(-next * current + 1)
|
|
elif (current.is_annihilation == next.is_annihilation and
|
|
isinstance(current, FermionOp) and isinstance(next, FermionOp)):
|
|
new_factors.append(-next * current)
|
|
else:
|
|
new_factors.append(next * current)
|
|
|
|
if n == len(factors) - 1:
|
|
new_factors.append(factors[-1])
|
|
|
|
if new_factors == factors:
|
|
return product
|
|
else:
|
|
expr = Mul(*new_factors).expand()
|
|
return normal_ordered_form(expr,
|
|
recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth + 1,
|
|
independent=independent)
|
|
|
|
|
|
def _normal_ordered_form_terms(expr, independent=False, recursive_limit=10,
|
|
_recursive_depth=0):
|
|
"""
|
|
Helper function for normal_ordered_form: loop through each term in an
|
|
addition expression and call _normal_ordered_form_factor to perform the
|
|
factor to an normally ordered expression.
|
|
"""
|
|
|
|
new_terms = []
|
|
for term in expr.args:
|
|
if isinstance(term, Mul):
|
|
new_term = _normal_ordered_form_factor(
|
|
term, recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth, independent=independent)
|
|
new_terms.append(new_term)
|
|
else:
|
|
new_terms.append(term)
|
|
|
|
return Add(*new_terms)
|
|
|
|
|
|
def normal_ordered_form(expr, independent=False, recursive_limit=10,
|
|
_recursive_depth=0):
|
|
"""Write an expression with bosonic or fermionic operators on normal
|
|
ordered form, where each term is normally ordered. Note that this
|
|
normal ordered form is equivalent to the original expression.
|
|
|
|
Parameters
|
|
==========
|
|
|
|
expr : expression
|
|
The expression write on normal ordered form.
|
|
independent : bool (default False)
|
|
Whether to consider operator with different names as operating in
|
|
different Hilbert spaces. If False, the (anti-)commutation is left
|
|
explicit.
|
|
recursive_limit : int (default 10)
|
|
The number of allowed recursive applications of the function.
|
|
|
|
Examples
|
|
========
|
|
|
|
>>> from sympy.physics.quantum import Dagger
|
|
>>> from sympy.physics.quantum.boson import BosonOp
|
|
>>> from sympy.physics.quantum.operatorordering import normal_ordered_form
|
|
>>> a = BosonOp("a")
|
|
>>> normal_ordered_form(a * Dagger(a))
|
|
1 + Dagger(a)*a
|
|
"""
|
|
|
|
if _recursive_depth > recursive_limit:
|
|
warnings.warn("Too many recursions, aborting")
|
|
return expr
|
|
|
|
if isinstance(expr, Add):
|
|
return _normal_ordered_form_terms(expr,
|
|
recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth,
|
|
independent=independent)
|
|
elif isinstance(expr, Mul):
|
|
return _normal_ordered_form_factor(expr,
|
|
recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth,
|
|
independent=independent)
|
|
else:
|
|
return expr
|
|
|
|
|
|
def _normal_order_factor(product, recursive_limit=10, _recursive_depth=0):
|
|
"""
|
|
Helper function for normal_order: Normal order a multiplication expression
|
|
with bosonic or fermionic operators. In general the resulting operator
|
|
expression will not be equivalent to original product.
|
|
"""
|
|
|
|
factors = _expand_powers(product)
|
|
|
|
n = 0
|
|
new_factors = []
|
|
while n < len(factors) - 1:
|
|
|
|
if (isinstance(factors[n], BosonOp) and
|
|
factors[n].is_annihilation):
|
|
# boson
|
|
if not isinstance(factors[n + 1], BosonOp):
|
|
new_factors.append(factors[n])
|
|
else:
|
|
if factors[n + 1].is_annihilation:
|
|
new_factors.append(factors[n])
|
|
else:
|
|
if factors[n].args[0] != factors[n + 1].args[0]:
|
|
new_factors.append(factors[n + 1] * factors[n])
|
|
else:
|
|
new_factors.append(factors[n + 1] * factors[n])
|
|
n += 1
|
|
|
|
elif (isinstance(factors[n], FermionOp) and
|
|
factors[n].is_annihilation):
|
|
# fermion
|
|
if not isinstance(factors[n + 1], FermionOp):
|
|
new_factors.append(factors[n])
|
|
else:
|
|
if factors[n + 1].is_annihilation:
|
|
new_factors.append(factors[n])
|
|
else:
|
|
if factors[n].args[0] != factors[n + 1].args[0]:
|
|
new_factors.append(-factors[n + 1] * factors[n])
|
|
else:
|
|
new_factors.append(-factors[n + 1] * factors[n])
|
|
n += 1
|
|
|
|
else:
|
|
new_factors.append(factors[n])
|
|
|
|
n += 1
|
|
|
|
if n == len(factors) - 1:
|
|
new_factors.append(factors[-1])
|
|
|
|
if new_factors == factors:
|
|
return product
|
|
else:
|
|
expr = Mul(*new_factors).expand()
|
|
return normal_order(expr,
|
|
recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth + 1)
|
|
|
|
|
|
def _normal_order_terms(expr, recursive_limit=10, _recursive_depth=0):
|
|
"""
|
|
Helper function for normal_order: look through each term in an addition
|
|
expression and call _normal_order_factor to perform the normal ordering
|
|
on the factors.
|
|
"""
|
|
|
|
new_terms = []
|
|
for term in expr.args:
|
|
if isinstance(term, Mul):
|
|
new_term = _normal_order_factor(term,
|
|
recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth)
|
|
new_terms.append(new_term)
|
|
else:
|
|
new_terms.append(term)
|
|
|
|
return Add(*new_terms)
|
|
|
|
|
|
def normal_order(expr, recursive_limit=10, _recursive_depth=0):
|
|
"""Normal order an expression with bosonic or fermionic operators. Note
|
|
that this normal order is not equivalent to the original expression, but
|
|
the creation and annihilation operators in each term in expr is reordered
|
|
so that the expression becomes normal ordered.
|
|
|
|
Parameters
|
|
==========
|
|
|
|
expr : expression
|
|
The expression to normal order.
|
|
|
|
recursive_limit : int (default 10)
|
|
The number of allowed recursive applications of the function.
|
|
|
|
Examples
|
|
========
|
|
|
|
>>> from sympy.physics.quantum import Dagger
|
|
>>> from sympy.physics.quantum.boson import BosonOp
|
|
>>> from sympy.physics.quantum.operatorordering import normal_order
|
|
>>> a = BosonOp("a")
|
|
>>> normal_order(a * Dagger(a))
|
|
Dagger(a)*a
|
|
"""
|
|
if _recursive_depth > recursive_limit:
|
|
warnings.warn("Too many recursions, aborting")
|
|
return expr
|
|
|
|
if isinstance(expr, Add):
|
|
return _normal_order_terms(expr, recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth)
|
|
elif isinstance(expr, Mul):
|
|
return _normal_order_factor(expr, recursive_limit=recursive_limit,
|
|
_recursive_depth=_recursive_depth)
|
|
else:
|
|
return expr
|