|
"""Bosonic quantum operators.""" |
|
|
|
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 |
|
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: |
|
|
|
if not self.is_annihilation and other.is_annihilation: |
|
return S.NegativeOne |
|
|
|
elif 'independent' in hints and hints['independent']: |
|
|
|
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']: |
|
|
|
return 2 * self * other |
|
|
|
return None |
|
|
|
def _eval_adjoint(self): |
|
return BosonOp(str(self.name), not self.is_annihilation) |
|
|
|
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_from_right_to_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_from_right_to_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 |
|
|