Source code for qnet.algebra.library.fock_operators

"""Collection of operators that act on a bosonic Fock space"""
import re
from abc import ABCMeta
from collections import OrderedDict

from ..core.hilbert_space_algebra import LocalSpace
from ..core.algebraic_properties import implied_local_space, match_replace
from ..core.operator_algebra import LocalOperator, PseudoInverse
from ...utils.properties_for_args import properties_for_args

__all__ = [
    'Destroy', 'Create', 'Phase', 'Displace', 'Squeeze']


[docs]class Destroy(LocalOperator): """Bosonic annihilation operator It obeys the bosonic commutation relation:: >>> Destroy(hs=1) * Create(hs=1) - Create(hs=1) * Destroy(hs=1) IdentityOperator >>> Destroy(hs=1) * Create(hs=2) - Create(hs=2) * Destroy(hs=1) ZeroOperator """ _identifier = 'a' _dagger = False _rx_identifier = re.compile('^[A-Za-z][A-Za-z0-9]*$') def __init__(self, *, hs): super().__init__(hs=hs) def _adjoint(self): return Create(hs=self.space) def _pseudo_inverse(self): return PseudoInverse(self) @property def identifier(self): """The identifier (symbol) that is used when printing the annihilation operator. This is identical to the identifier of :class:`Create`. A custom identifier for both :class:`Destroy` and :class:`Create` can be set through the `local_identifiers` parameter of the associated Hilbert space:: >>> hs_custom = LocalSpace(0, local_identifiers={'Destroy': 'b'}) >>> Create(hs=hs_custom).identifier 'b' >>> Destroy(hs=hs_custom).identifier 'b' """ identifier = self._hs._local_identifiers.get( self.__class__.__name__, self._hs._local_identifiers.get( 'Create', self._identifier)) if not self._rx_identifier.match(identifier): raise ValueError( "identifier '%s' does not match pattern '%s'" % (identifier, self._rx_identifier.pattern)) return identifier
[docs]class Create(LocalOperator): """Bosonic creation operator This is the adjoint of :class:`Destroy`. """ _identifier = 'a' _dagger = True _rx_identifier = re.compile('^[A-Za-z][A-Za-z0-9]*$') def __init__(self, *, hs): super().__init__(hs=hs) def _adjoint(self): return Destroy(hs=self.space) def _pseudo_inverse(self): return PseudoInverse(self) @property def identifier(self): """The identifier (symbols) that is used when printing the creation operator. This is identical to the identifier of :class:`Destroy`""" identifier = self._hs._local_identifiers.get( self.__class__.__name__, self._hs._local_identifiers.get( 'Destroy', self._identifier)) if not self._rx_identifier.match(identifier): raise ValueError( "identifier '%s' does not match pattern '%s'" % (identifier, self._rx_identifier.pattern)) return identifier
[docs]@properties_for_args class Phase(LocalOperator): r"""Unitary "phase" operator .. math:: \op{P}_{\rm hs}(\phi) = \exp\left(i \phi \Op{a}_{\rm hs}^\dagger \Op{a}_{\rm hs}\right) where :math:`a_{\rm hs}` is the annihilation operator acting on the :class:`.LocalSpace` `hs`. Args: phase (Scalar): the phase $\phi$ hs (HilbertSpace or int or str): The Hilbert space on which the operator acts Printers should represent this operator with the default identifier:: >>> Phase._identifier 'Phase' A custom identifier may be define using `hs`'s `local_identifiers` argument. """ _identifier = 'Phase' _arg_names = ('phase', ) _rules = OrderedDict() simplifications = [implied_local_space(keys=['hs', ]), match_replace] def _adjoint(self): return Phase.create(-self.phase.conjugate(), hs=self.space) def _pseudo_inverse(self): return Phase.create(-self.phase, hs=self.space)
[docs]@properties_for_args class Displace(LocalOperator): r"""Unitary coherent displacement operator .. math:: \op{D}_{\rm hs}(\alpha) = \exp\left({\alpha \Op{a}_{\rm hs}^\dagger - \alpha^* \Op{a}_{\rm hs}}\right) where :math:`\Op{a}_{\rm hs}` is the annihilation operator acting on the :class:`.LocalSpace` `hs`. Args: displacement (Scalar): the displacement amplitude $\alpha$ hs (HilbertSpace or int or str): The Hilbert space on which the operator acts Printers should represent this operator with the default identifier:: >>> Displace._identifier 'D' A custom identifier may be define using `hs`'s `local_identifiers` argument. """ _identifier = 'D' _nargs = 1 _arg_names = ('displacement', ) _rules = OrderedDict() simplifications = [implied_local_space(keys=['hs', ]), match_replace] def _adjoint(self): return Displace.create(-self.displacement, hs=self.space) _pseudo_inverse = _adjoint
[docs]@properties_for_args class Squeeze(LocalOperator): r"""Unitary squeezing operator .. math:: \Op{S}_{\rm hs}(\eta) = \exp {\left( \frac{\eta}{2} {\Op{a}_{\rm hs}^\dagger}^2 - \frac{\eta^*}{2} {\Op{a}_{\rm hs}}^2 \right)} where :math:`\Op{a}_{\rm hs}` is the annihilation operator acting on the :class:`.LocalSpace` `hs`. Args: squeezing_factor (Scalar): the squeezing factor $\eta$ hs (HilbertSpace or int or str): The Hilbert space on which the operator acts Printers should represent this operator with the default identifier:: >>> Squeeze._identifier 'Squeeze' A custom identifier may be define using `hs`'s `local_identifiers` argument. """ _identifier = "Squeeze" _arg_names = ('squeezing_factor', ) _rules = OrderedDict() simplifications = [implied_local_space(keys=['hs', ]), match_replace] def _adjoint(self): return Squeeze(-self.squeezing_factor, hs=self.space) _pseudo_inverse = _adjoint