Spaces:
Running
Running
File size: 10,296 Bytes
6a86ad5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
"""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
|