|
|
"""Symbolic inner product."""
from sympy.core.expr import Expr from sympy.functions.elementary.complexes import conjugate from sympy.printing.pretty.stringpict import prettyForm from sympy.physics.quantum.dagger import Dagger from sympy.physics.quantum.state import KetBase, BraBase
__all__ = [ 'InnerProduct' ]
# InnerProduct is not an QExpr because it is really just a regular commutative # number. We have gone back and forth about this, but we gain a lot by having # it subclass Expr. The main challenges were getting Dagger to work # (we use _eval_conjugate) and represent (we can use atoms and subs). Having # it be an Expr, mean that there are no commutative QExpr subclasses, # which simplifies the design of everything.
class InnerProduct(Expr): """An unevaluated inner product between a Bra and a Ket [1].
Parameters ==========
bra : BraBase or subclass The bra on the left side of the inner product. ket : KetBase or subclass The ket on the right side of the inner product.
Examples ========
Create an InnerProduct and check its properties:
>>> from sympy.physics.quantum import Bra, Ket >>> b = Bra('b') >>> k = Ket('k') >>> ip = b*k >>> ip <b|k> >>> ip.bra <b| >>> ip.ket |k>
In simple products of kets and bras inner products will be automatically identified and created::
>>> b*k <b|k>
But in more complex expressions, there is ambiguity in whether inner or outer products should be created::
>>> k*b*k*b |k><b|*|k>*<b|
A user can force the creation of a inner products in a complex expression by using parentheses to group the bra and ket::
>>> k*(b*k)*b <b|k>*|k>*<b|
Notice how the inner product <b|k> moved to the left of the expression because inner products are commutative complex numbers.
References ==========
.. [1] https://en.wikipedia.org/wiki/Inner_product """
is_complex = True
def __new__(cls, bra, ket): if not isinstance(ket, KetBase): raise TypeError('KetBase subclass expected, got: %r' % ket) if not isinstance(bra, BraBase): raise TypeError('BraBase subclass expected, got: %r' % ket) obj = Expr.__new__(cls, bra, ket) return obj
@property def bra(self): return self.args[0]
@property def ket(self): return self.args[1]
def _eval_conjugate(self): return InnerProduct(Dagger(self.ket), Dagger(self.bra))
def _sympyrepr(self, printer, *args): return '%s(%s,%s)' % (self.__class__.__name__, printer._print(self.bra, *args), printer._print(self.ket, *args))
def _sympystr(self, printer, *args): sbra = printer._print(self.bra) sket = printer._print(self.ket) return '%s|%s' % (sbra[:-1], sket[1:])
def _pretty(self, printer, *args): # Print state contents bra = self.bra._print_contents_pretty(printer, *args) ket = self.ket._print_contents_pretty(printer, *args) # Print brackets height = max(bra.height(), ket.height()) use_unicode = printer._use_unicode lbracket, _ = self.bra._pretty_brackets(height, use_unicode) cbracket, rbracket = self.ket._pretty_brackets(height, use_unicode) # Build innerproduct pform = prettyForm(*bra.left(lbracket)) pform = prettyForm(*pform.right(cbracket)) pform = prettyForm(*pform.right(ket)) pform = prettyForm(*pform.right(rbracket)) return pform
def _latex(self, printer, *args): bra_label = self.bra._print_contents_latex(printer, *args) ket = printer._print(self.ket, *args) return r'\left\langle %s \right. %s' % (bra_label, ket)
def doit(self, **hints): try: r = self.ket._eval_innerproduct(self.bra, **hints) except NotImplementedError: try: r = conjugate( self.bra.dual._eval_innerproduct(self.ket.dual, **hints) ) except NotImplementedError: r = None if r is not None: return r return self
|