/
innerproduct.py
137 lines (109 loc) · 4.18 KB
/
innerproduct.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""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