|
|
"""Bosonic quantum operators."""
from sympy.core.mul import Mul from sympy.core.numbers import Integer from sympy.core.singleton import S from sympy.functions.elementary.complexes import conjugate from sympy.functions.elementary.exponential import exp from sympy.functions.elementary.miscellaneous import sqrt from sympy.physics.quantum import Operator from sympy.physics.quantum import HilbertSpace, FockSpace, Ket, Bra, IdentityOperator from sympy.functions.special.tensor_functions import KroneckerDelta
__all__ = [ 'BosonOp', 'BosonFockKet', 'BosonFockBra', 'BosonCoherentKet', 'BosonCoherentBra' ]
class BosonOp(Operator): """A bosonic operator that satisfies [a, Dagger(a)] == 1.
Parameters ==========
name : str A string that labels the bosonic mode.
annihilation : bool A bool that indicates if the bosonic operator is an annihilation (True, default value) or creation operator (False)
Examples ========
>>> from sympy.physics.quantum import Dagger, Commutator >>> from sympy.physics.quantum.boson import BosonOp >>> a = BosonOp("a") >>> Commutator(a, Dagger(a)).doit() 1 """
@property def name(self): return self.args[0]
@property def is_annihilation(self): return bool(self.args[1])
@classmethod def default_args(self): return ("a", True)
def __new__(cls, *args, **hints): if not len(args) in [1, 2]: raise ValueError('1 or 2 parameters expected, got %s' % args)
if len(args) == 1: args = (args[0], S.One)
if len(args) == 2: args = (args[0], Integer(args[1]))
return Operator.__new__(cls, *args)
def _eval_commutator_BosonOp(self, other, **hints): if self.name == other.name: # [a^\dagger, a] = -1 if not self.is_annihilation and other.is_annihilation: return S.NegativeOne
elif 'independent' in hints and hints['independent']: # [a, b] = 0 return S.Zero
return None
def _eval_commutator_FermionOp(self, other, **hints): return S.Zero
def _eval_anticommutator_BosonOp(self, other, **hints): if 'independent' in hints and hints['independent']: # {a, b} = 2 * a * b, because [a, b] = 0 return 2 * self * other
return None
def _eval_adjoint(self): return BosonOp(str(self.name), not self.is_annihilation)
def __mul__(self, other):
if other == IdentityOperator(2): return self
if isinstance(other, Mul): args1 = tuple(arg for arg in other.args if arg.is_commutative) args2 = tuple(arg for arg in other.args if not arg.is_commutative) x = self for y in args2: x = x * y return Mul(*args1) * x
return Mul(self, other)
def _print_contents_latex(self, printer, *args): if self.is_annihilation: return r'{%s}' % str(self.name) else: return r'{{%s}^\dagger}' % str(self.name)
def _print_contents(self, printer, *args): if self.is_annihilation: return r'%s' % str(self.name) else: return r'Dagger(%s)' % str(self.name)
def _print_contents_pretty(self, printer, *args): from sympy.printing.pretty.stringpict import prettyForm pform = printer._print(self.args[0], *args) if self.is_annihilation: return pform else: return pform**prettyForm('\N{DAGGER}')
class BosonFockKet(Ket): """Fock state ket for a bosonic mode.
Parameters ==========
n : Number The Fock state number.
"""
def __new__(cls, n): return Ket.__new__(cls, n)
@property def n(self): return self.label[0]
@classmethod def dual_class(self): return BosonFockBra
@classmethod def _eval_hilbert_space(cls, label): return FockSpace()
def _eval_innerproduct_BosonFockBra(self, bra, **hints): return KroneckerDelta(self.n, bra.n)
def _apply_operator_BosonOp(self, op, **options): if op.is_annihilation: return sqrt(self.n) * BosonFockKet(self.n - 1) else: return sqrt(self.n + 1) * BosonFockKet(self.n + 1)
class BosonFockBra(Bra): """Fock state bra for a bosonic mode.
Parameters ==========
n : Number The Fock state number.
"""
def __new__(cls, n): return Bra.__new__(cls, n)
@property def n(self): return self.label[0]
@classmethod def dual_class(self): return BosonFockKet
@classmethod def _eval_hilbert_space(cls, label): return FockSpace()
class BosonCoherentKet(Ket): """Coherent state ket for a bosonic mode.
Parameters ==========
alpha : Number, Symbol The complex amplitude of the coherent state.
"""
def __new__(cls, alpha): return Ket.__new__(cls, alpha)
@property def alpha(self): return self.label[0]
@classmethod def dual_class(self): return BosonCoherentBra
@classmethod def _eval_hilbert_space(cls, label): return HilbertSpace()
def _eval_innerproduct_BosonCoherentBra(self, bra, **hints): if self.alpha == bra.alpha: return S.One else: return exp(-(abs(self.alpha)**2 + abs(bra.alpha)**2 - 2 * conjugate(bra.alpha) * self.alpha)/2)
def _apply_operator_BosonOp(self, op, **options): if op.is_annihilation: return self.alpha * self else: return None
class BosonCoherentBra(Bra): """Coherent state bra for a bosonic mode.
Parameters ==========
alpha : Number, Symbol The complex amplitude of the coherent state.
"""
def __new__(cls, alpha): return Bra.__new__(cls, alpha)
@property def alpha(self): return self.label[0]
@classmethod def dual_class(self): return BosonCoherentKet
def _apply_operator_BosonOp(self, op, **options): if not op.is_annihilation: return self.alpha * self else: return None
|