cranky-coder08's picture
Add files using upload-large-folder tool
ac2f8e9 verified
raw
history blame
4.3 kB
"""Symbolic inner product."""
from sympy.core.expr import Expr
from sympy.core.kind import NumberKind
from sympy.functions.elementary.complexes import conjugate
from sympy.printing.pretty.stringpict import prettyForm
from sympy.physics.quantum.dagger import Dagger
__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 quantum expressions, inner products will be automatically
identified and created::
>>> b*k
<b|k>
In more complex expressions, where there is ambiguity in whether inner or
outer products should be created, inner products have high priority::
>>> 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
"""
kind = NumberKind
is_complex = True
def __new__(cls, bra, ket):
# Keep the import of BraBase and KetBase here to avoid problems
# with circular imports.
from sympy.physics.quantum.state import KetBase, BraBase
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