kind.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. """Kinds for Operators, Bras, and Kets.
  2. This module defines kinds for operators, bras, and kets. These are useful
  3. in various places in ``sympy.physics.quantum`` as you often want to know
  4. what the kind is of a compound expression. For example, if you multiply
  5. an operator, bra, or ket by a number, you get back another operator, bra,
  6. or ket - even though if you did an ``isinstance`` check you would find that
  7. you have a ``Mul`` instead. The kind system is meant to give you a quick
  8. way of determining how a compound expression behaves in terms of lower
  9. level kinds.
  10. The resolution calculation of kinds for compound expressions can be found
  11. either in container classes or in functions that are registered with
  12. kind dispatchers.
  13. """
  14. from sympy.core.mul import Mul
  15. from sympy.core.kind import Kind, _NumberKind
  16. __all__ = [
  17. '_KetKind',
  18. 'KetKind',
  19. '_BraKind',
  20. 'BraKind',
  21. '_OperatorKind',
  22. 'OperatorKind',
  23. ]
  24. class _KetKind(Kind):
  25. """A kind for quantum kets."""
  26. def __new__(cls):
  27. obj = super().__new__(cls)
  28. return obj
  29. def __repr__(self):
  30. return "KetKind"
  31. # Create an instance as many situations need this.
  32. KetKind = _KetKind()
  33. class _BraKind(Kind):
  34. """A kind for quantum bras."""
  35. def __new__(cls):
  36. obj = super().__new__(cls)
  37. return obj
  38. def __repr__(self):
  39. return "BraKind"
  40. # Create an instance as many situations need this.
  41. BraKind = _BraKind()
  42. from sympy.core.kind import Kind
  43. class _OperatorKind(Kind):
  44. """A kind for quantum operators."""
  45. def __new__(cls):
  46. obj = super().__new__(cls)
  47. return obj
  48. def __repr__(self):
  49. return "OperatorKind"
  50. # Create an instance as many situations need this.
  51. OperatorKind = _OperatorKind()
  52. #-----------------------------------------------------------------------------
  53. # Kind resolution.
  54. #-----------------------------------------------------------------------------
  55. # Note: We can't currently add kind dispatchers for the following combinations
  56. # as the Mul._kind_dispatcher is set to commutative and will also
  57. # register the opposite order, which isn't correct for these pairs:
  58. #
  59. # 1. (_OperatorKind, _KetKind)
  60. # 2. (_BraKind, _OperatorKind)
  61. # 3. (_BraKind, _KetKind)
  62. @Mul._kind_dispatcher.register(_NumberKind, _KetKind)
  63. def _mul_number_ket_kind(lhs, rhs):
  64. """Perform the kind calculation of NumberKind*KetKind -> KetKind."""
  65. return KetKind
  66. @Mul._kind_dispatcher.register(_NumberKind, _BraKind)
  67. def _mul_number_bra_kind(lhs, rhs):
  68. """Perform the kind calculation of NumberKind*BraKind -> BraKind."""
  69. return BraKind
  70. @Mul._kind_dispatcher.register(_NumberKind, _OperatorKind)
  71. def _mul_operator_kind(lhs, rhs):
  72. """Perform the kind calculation of NumberKind*OperatorKind -> OperatorKind."""
  73. return OperatorKind