260 lines
6.2 KiB
Python
260 lines
6.2 KiB
Python
"""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_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
|