innerproduct.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. """Symbolic inner product."""
  2. from sympy.core.expr import Expr
  3. from sympy.functions.elementary.complexes import conjugate
  4. from sympy.printing.pretty.stringpict import prettyForm
  5. from sympy.physics.quantum.dagger import Dagger
  6. from sympy.physics.quantum.state import KetBase, BraBase
  7. __all__ = [
  8. 'InnerProduct'
  9. ]
  10. # InnerProduct is not an QExpr because it is really just a regular commutative
  11. # number. We have gone back and forth about this, but we gain a lot by having
  12. # it subclass Expr. The main challenges were getting Dagger to work
  13. # (we use _eval_conjugate) and represent (we can use atoms and subs). Having
  14. # it be an Expr, mean that there are no commutative QExpr subclasses,
  15. # which simplifies the design of everything.
  16. class InnerProduct(Expr):
  17. """An unevaluated inner product between a Bra and a Ket [1].
  18. Parameters
  19. ==========
  20. bra : BraBase or subclass
  21. The bra on the left side of the inner product.
  22. ket : KetBase or subclass
  23. The ket on the right side of the inner product.
  24. Examples
  25. ========
  26. Create an InnerProduct and check its properties:
  27. >>> from sympy.physics.quantum import Bra, Ket
  28. >>> b = Bra('b')
  29. >>> k = Ket('k')
  30. >>> ip = b*k
  31. >>> ip
  32. <b|k>
  33. >>> ip.bra
  34. <b|
  35. >>> ip.ket
  36. |k>
  37. In simple products of kets and bras inner products will be automatically
  38. identified and created::
  39. >>> b*k
  40. <b|k>
  41. But in more complex expressions, there is ambiguity in whether inner or
  42. outer products should be created::
  43. >>> k*b*k*b
  44. |k><b|*|k>*<b|
  45. A user can force the creation of a inner products in a complex expression
  46. by using parentheses to group the bra and ket::
  47. >>> k*(b*k)*b
  48. <b|k>*|k>*<b|
  49. Notice how the inner product <b|k> moved to the left of the expression
  50. because inner products are commutative complex numbers.
  51. References
  52. ==========
  53. .. [1] https://en.wikipedia.org/wiki/Inner_product
  54. """
  55. is_complex = True
  56. def __new__(cls, bra, ket):
  57. if not isinstance(ket, KetBase):
  58. raise TypeError('KetBase subclass expected, got: %r' % ket)
  59. if not isinstance(bra, BraBase):
  60. raise TypeError('BraBase subclass expected, got: %r' % ket)
  61. obj = Expr.__new__(cls, bra, ket)
  62. return obj
  63. @property
  64. def bra(self):
  65. return self.args[0]
  66. @property
  67. def ket(self):
  68. return self.args[1]
  69. def _eval_conjugate(self):
  70. return InnerProduct(Dagger(self.ket), Dagger(self.bra))
  71. def _sympyrepr(self, printer, *args):
  72. return '%s(%s,%s)' % (self.__class__.__name__,
  73. printer._print(self.bra, *args), printer._print(self.ket, *args))
  74. def _sympystr(self, printer, *args):
  75. sbra = printer._print(self.bra)
  76. sket = printer._print(self.ket)
  77. return '%s|%s' % (sbra[:-1], sket[1:])
  78. def _pretty(self, printer, *args):
  79. # Print state contents
  80. bra = self.bra._print_contents_pretty(printer, *args)
  81. ket = self.ket._print_contents_pretty(printer, *args)
  82. # Print brackets
  83. height = max(bra.height(), ket.height())
  84. use_unicode = printer._use_unicode
  85. lbracket, _ = self.bra._pretty_brackets(height, use_unicode)
  86. cbracket, rbracket = self.ket._pretty_brackets(height, use_unicode)
  87. # Build innerproduct
  88. pform = prettyForm(*bra.left(lbracket))
  89. pform = prettyForm(*pform.right(cbracket))
  90. pform = prettyForm(*pform.right(ket))
  91. pform = prettyForm(*pform.right(rbracket))
  92. return pform
  93. def _latex(self, printer, *args):
  94. bra_label = self.bra._print_contents_latex(printer, *args)
  95. ket = printer._print(self.ket, *args)
  96. return r'\left\langle %s \right. %s' % (bra_label, ket)
  97. def doit(self, **hints):
  98. try:
  99. r = self.ket._eval_innerproduct(self.bra, **hints)
  100. except NotImplementedError:
  101. try:
  102. r = conjugate(
  103. self.bra.dual._eval_innerproduct(self.ket.dual, **hints)
  104. )
  105. except NotImplementedError:
  106. r = None
  107. if r is not None:
  108. return r
  109. return self