|
|
"""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' |
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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): |
|
|
|
|
|
|
|
|
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): |
|
|
|
|
|
bra = self.bra._print_contents_pretty(printer, *args) |
|
|
ket = self.ket._print_contents_pretty(printer, *args) |
|
|
|
|
|
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) |
|
|
|
|
|
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 |
|
|
|