123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- """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 Operator, 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:
- if isinstance(factors[n], BosonOp):
- # boson
- if not isinstance(factors[n + 1], BosonOp):
- new_factors.append(factors[n])
- elif factors[n].is_annihilation == factors[n + 1].is_annihilation:
- if (independent and
- str(factors[n].name) > str(factors[n + 1].name)):
- new_factors.append(factors[n + 1])
- new_factors.append(factors[n])
- n += 1
- else:
- new_factors.append(factors[n])
- elif not factors[n].is_annihilation:
- 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]:
- if independent:
- c = 0
- else:
- c = Commutator(factors[n], factors[n + 1])
- new_factors.append(factors[n + 1] * factors[n] + c)
- else:
- c = Commutator(factors[n], factors[n + 1])
- new_factors.append(
- factors[n + 1] * factors[n] + c.doit())
- n += 1
- elif isinstance(factors[n], FermionOp):
- # fermion
- if not isinstance(factors[n + 1], FermionOp):
- new_factors.append(factors[n])
- elif factors[n].is_annihilation == factors[n + 1].is_annihilation:
- if (independent and
- str(factors[n].name) > str(factors[n + 1].name)):
- new_factors.append(factors[n + 1])
- new_factors.append(factors[n])
- n += 1
- else:
- new_factors.append(factors[n])
- elif not factors[n].is_annihilation:
- 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]:
- if independent:
- c = 0
- else:
- c = AntiCommutator(factors[n], factors[n + 1])
- new_factors.append(-factors[n + 1] * factors[n] + c)
- else:
- c = AntiCommutator(factors[n], factors[n + 1])
- new_factors.append(
- -factors[n + 1] * factors[n] + c.doit())
- n += 1
- elif isinstance(factors[n], Operator):
- if isinstance(factors[n + 1], (BosonOp, FermionOp)):
- new_factors.append(factors[n + 1])
- new_factors.append(factors[n])
- n += 1
- else:
- new_factors.append(factors[n])
- 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_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.
- 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
|