图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

675 lines
17 KiB

  1. """Pauli operators and states"""
  2. from sympy.core.add import Add
  3. from sympy.core.mul import Mul
  4. from sympy.core.numbers import I
  5. from sympy.core.power import Pow
  6. from sympy.core.singleton import S
  7. from sympy.functions.elementary.exponential import exp
  8. from sympy.physics.quantum import Operator, Ket, Bra
  9. from sympy.physics.quantum import ComplexSpace
  10. from sympy.matrices import Matrix
  11. from sympy.functions.special.tensor_functions import KroneckerDelta
  12. __all__ = [
  13. 'SigmaX', 'SigmaY', 'SigmaZ', 'SigmaMinus', 'SigmaPlus', 'SigmaZKet',
  14. 'SigmaZBra', 'qsimplify_pauli'
  15. ]
  16. class SigmaOpBase(Operator):
  17. """Pauli sigma operator, base class"""
  18. @property
  19. def name(self):
  20. return self.args[0]
  21. @property
  22. def use_name(self):
  23. return bool(self.args[0]) is not False
  24. @classmethod
  25. def default_args(self):
  26. return (False,)
  27. def __new__(cls, *args, **hints):
  28. return Operator.__new__(cls, *args, **hints)
  29. def _eval_commutator_BosonOp(self, other, **hints):
  30. return S.Zero
  31. class SigmaX(SigmaOpBase):
  32. """Pauli sigma x operator
  33. Parameters
  34. ==========
  35. name : str
  36. An optional string that labels the operator. Pauli operators with
  37. different names commute.
  38. Examples
  39. ========
  40. >>> from sympy.physics.quantum import represent
  41. >>> from sympy.physics.quantum.pauli import SigmaX
  42. >>> sx = SigmaX()
  43. >>> sx
  44. SigmaX()
  45. >>> represent(sx)
  46. Matrix([
  47. [0, 1],
  48. [1, 0]])
  49. """
  50. def __new__(cls, *args, **hints):
  51. return SigmaOpBase.__new__(cls, *args, **hints)
  52. def _eval_commutator_SigmaY(self, other, **hints):
  53. if self.name != other.name:
  54. return S.Zero
  55. else:
  56. return 2 * I * SigmaZ(self.name)
  57. def _eval_commutator_SigmaZ(self, other, **hints):
  58. if self.name != other.name:
  59. return S.Zero
  60. else:
  61. return - 2 * I * SigmaY(self.name)
  62. def _eval_commutator_BosonOp(self, other, **hints):
  63. return S.Zero
  64. def _eval_anticommutator_SigmaY(self, other, **hints):
  65. return S.Zero
  66. def _eval_anticommutator_SigmaZ(self, other, **hints):
  67. return S.Zero
  68. def _eval_adjoint(self):
  69. return self
  70. def _print_contents_latex(self, printer, *args):
  71. if self.use_name:
  72. return r'{\sigma_x^{(%s)}}' % str(self.name)
  73. else:
  74. return r'{\sigma_x}'
  75. def _print_contents(self, printer, *args):
  76. return 'SigmaX()'
  77. def _eval_power(self, e):
  78. if e.is_Integer and e.is_positive:
  79. return SigmaX(self.name).__pow__(int(e) % 2)
  80. def _represent_default_basis(self, **options):
  81. format = options.get('format', 'sympy')
  82. if format == 'sympy':
  83. return Matrix([[0, 1], [1, 0]])
  84. else:
  85. raise NotImplementedError('Representation in format ' +
  86. format + ' not implemented.')
  87. class SigmaY(SigmaOpBase):
  88. """Pauli sigma y operator
  89. Parameters
  90. ==========
  91. name : str
  92. An optional string that labels the operator. Pauli operators with
  93. different names commute.
  94. Examples
  95. ========
  96. >>> from sympy.physics.quantum import represent
  97. >>> from sympy.physics.quantum.pauli import SigmaY
  98. >>> sy = SigmaY()
  99. >>> sy
  100. SigmaY()
  101. >>> represent(sy)
  102. Matrix([
  103. [0, -I],
  104. [I, 0]])
  105. """
  106. def __new__(cls, *args, **hints):
  107. return SigmaOpBase.__new__(cls, *args)
  108. def _eval_commutator_SigmaZ(self, other, **hints):
  109. if self.name != other.name:
  110. return S.Zero
  111. else:
  112. return 2 * I * SigmaX(self.name)
  113. def _eval_commutator_SigmaX(self, other, **hints):
  114. if self.name != other.name:
  115. return S.Zero
  116. else:
  117. return - 2 * I * SigmaZ(self.name)
  118. def _eval_anticommutator_SigmaX(self, other, **hints):
  119. return S.Zero
  120. def _eval_anticommutator_SigmaZ(self, other, **hints):
  121. return S.Zero
  122. def _eval_adjoint(self):
  123. return self
  124. def _print_contents_latex(self, printer, *args):
  125. if self.use_name:
  126. return r'{\sigma_y^{(%s)}}' % str(self.name)
  127. else:
  128. return r'{\sigma_y}'
  129. def _print_contents(self, printer, *args):
  130. return 'SigmaY()'
  131. def _eval_power(self, e):
  132. if e.is_Integer and e.is_positive:
  133. return SigmaY(self.name).__pow__(int(e) % 2)
  134. def _represent_default_basis(self, **options):
  135. format = options.get('format', 'sympy')
  136. if format == 'sympy':
  137. return Matrix([[0, -I], [I, 0]])
  138. else:
  139. raise NotImplementedError('Representation in format ' +
  140. format + ' not implemented.')
  141. class SigmaZ(SigmaOpBase):
  142. """Pauli sigma z operator
  143. Parameters
  144. ==========
  145. name : str
  146. An optional string that labels the operator. Pauli operators with
  147. different names commute.
  148. Examples
  149. ========
  150. >>> from sympy.physics.quantum import represent
  151. >>> from sympy.physics.quantum.pauli import SigmaZ
  152. >>> sz = SigmaZ()
  153. >>> sz ** 3
  154. SigmaZ()
  155. >>> represent(sz)
  156. Matrix([
  157. [1, 0],
  158. [0, -1]])
  159. """
  160. def __new__(cls, *args, **hints):
  161. return SigmaOpBase.__new__(cls, *args)
  162. def _eval_commutator_SigmaX(self, other, **hints):
  163. if self.name != other.name:
  164. return S.Zero
  165. else:
  166. return 2 * I * SigmaY(self.name)
  167. def _eval_commutator_SigmaY(self, other, **hints):
  168. if self.name != other.name:
  169. return S.Zero
  170. else:
  171. return - 2 * I * SigmaX(self.name)
  172. def _eval_anticommutator_SigmaX(self, other, **hints):
  173. return S.Zero
  174. def _eval_anticommutator_SigmaY(self, other, **hints):
  175. return S.Zero
  176. def _eval_adjoint(self):
  177. return self
  178. def _print_contents_latex(self, printer, *args):
  179. if self.use_name:
  180. return r'{\sigma_z^{(%s)}}' % str(self.name)
  181. else:
  182. return r'{\sigma_z}'
  183. def _print_contents(self, printer, *args):
  184. return 'SigmaZ()'
  185. def _eval_power(self, e):
  186. if e.is_Integer and e.is_positive:
  187. return SigmaZ(self.name).__pow__(int(e) % 2)
  188. def _represent_default_basis(self, **options):
  189. format = options.get('format', 'sympy')
  190. if format == 'sympy':
  191. return Matrix([[1, 0], [0, -1]])
  192. else:
  193. raise NotImplementedError('Representation in format ' +
  194. format + ' not implemented.')
  195. class SigmaMinus(SigmaOpBase):
  196. """Pauli sigma minus operator
  197. Parameters
  198. ==========
  199. name : str
  200. An optional string that labels the operator. Pauli operators with
  201. different names commute.
  202. Examples
  203. ========
  204. >>> from sympy.physics.quantum import represent, Dagger
  205. >>> from sympy.physics.quantum.pauli import SigmaMinus
  206. >>> sm = SigmaMinus()
  207. >>> sm
  208. SigmaMinus()
  209. >>> Dagger(sm)
  210. SigmaPlus()
  211. >>> represent(sm)
  212. Matrix([
  213. [0, 0],
  214. [1, 0]])
  215. """
  216. def __new__(cls, *args, **hints):
  217. return SigmaOpBase.__new__(cls, *args)
  218. def _eval_commutator_SigmaX(self, other, **hints):
  219. if self.name != other.name:
  220. return S.Zero
  221. else:
  222. return -SigmaZ(self.name)
  223. def _eval_commutator_SigmaY(self, other, **hints):
  224. if self.name != other.name:
  225. return S.Zero
  226. else:
  227. return I * SigmaZ(self.name)
  228. def _eval_commutator_SigmaZ(self, other, **hints):
  229. return 2 * self
  230. def _eval_commutator_SigmaMinus(self, other, **hints):
  231. return SigmaZ(self.name)
  232. def _eval_anticommutator_SigmaZ(self, other, **hints):
  233. return S.Zero
  234. def _eval_anticommutator_SigmaX(self, other, **hints):
  235. return S.One
  236. def _eval_anticommutator_SigmaY(self, other, **hints):
  237. return I * S.NegativeOne
  238. def _eval_anticommutator_SigmaPlus(self, other, **hints):
  239. return S.One
  240. def _eval_adjoint(self):
  241. return SigmaPlus(self.name)
  242. def _eval_power(self, e):
  243. if e.is_Integer and e.is_positive:
  244. return S.Zero
  245. def _print_contents_latex(self, printer, *args):
  246. if self.use_name:
  247. return r'{\sigma_-^{(%s)}}' % str(self.name)
  248. else:
  249. return r'{\sigma_-}'
  250. def _print_contents(self, printer, *args):
  251. return 'SigmaMinus()'
  252. def _represent_default_basis(self, **options):
  253. format = options.get('format', 'sympy')
  254. if format == 'sympy':
  255. return Matrix([[0, 0], [1, 0]])
  256. else:
  257. raise NotImplementedError('Representation in format ' +
  258. format + ' not implemented.')
  259. class SigmaPlus(SigmaOpBase):
  260. """Pauli sigma plus operator
  261. Parameters
  262. ==========
  263. name : str
  264. An optional string that labels the operator. Pauli operators with
  265. different names commute.
  266. Examples
  267. ========
  268. >>> from sympy.physics.quantum import represent, Dagger
  269. >>> from sympy.physics.quantum.pauli import SigmaPlus
  270. >>> sp = SigmaPlus()
  271. >>> sp
  272. SigmaPlus()
  273. >>> Dagger(sp)
  274. SigmaMinus()
  275. >>> represent(sp)
  276. Matrix([
  277. [0, 1],
  278. [0, 0]])
  279. """
  280. def __new__(cls, *args, **hints):
  281. return SigmaOpBase.__new__(cls, *args)
  282. def _eval_commutator_SigmaX(self, other, **hints):
  283. if self.name != other.name:
  284. return S.Zero
  285. else:
  286. return SigmaZ(self.name)
  287. def _eval_commutator_SigmaY(self, other, **hints):
  288. if self.name != other.name:
  289. return S.Zero
  290. else:
  291. return I * SigmaZ(self.name)
  292. def _eval_commutator_SigmaZ(self, other, **hints):
  293. if self.name != other.name:
  294. return S.Zero
  295. else:
  296. return -2 * self
  297. def _eval_commutator_SigmaMinus(self, other, **hints):
  298. return SigmaZ(self.name)
  299. def _eval_anticommutator_SigmaZ(self, other, **hints):
  300. return S.Zero
  301. def _eval_anticommutator_SigmaX(self, other, **hints):
  302. return S.One
  303. def _eval_anticommutator_SigmaY(self, other, **hints):
  304. return I
  305. def _eval_anticommutator_SigmaMinus(self, other, **hints):
  306. return S.One
  307. def _eval_adjoint(self):
  308. return SigmaMinus(self.name)
  309. def _eval_mul(self, other):
  310. return self * other
  311. def _eval_power(self, e):
  312. if e.is_Integer and e.is_positive:
  313. return S.Zero
  314. def _print_contents_latex(self, printer, *args):
  315. if self.use_name:
  316. return r'{\sigma_+^{(%s)}}' % str(self.name)
  317. else:
  318. return r'{\sigma_+}'
  319. def _print_contents(self, printer, *args):
  320. return 'SigmaPlus()'
  321. def _represent_default_basis(self, **options):
  322. format = options.get('format', 'sympy')
  323. if format == 'sympy':
  324. return Matrix([[0, 1], [0, 0]])
  325. else:
  326. raise NotImplementedError('Representation in format ' +
  327. format + ' not implemented.')
  328. class SigmaZKet(Ket):
  329. """Ket for a two-level system quantum system.
  330. Parameters
  331. ==========
  332. n : Number
  333. The state number (0 or 1).
  334. """
  335. def __new__(cls, n):
  336. if n not in (0, 1):
  337. raise ValueError("n must be 0 or 1")
  338. return Ket.__new__(cls, n)
  339. @property
  340. def n(self):
  341. return self.label[0]
  342. @classmethod
  343. def dual_class(self):
  344. return SigmaZBra
  345. @classmethod
  346. def _eval_hilbert_space(cls, label):
  347. return ComplexSpace(2)
  348. def _eval_innerproduct_SigmaZBra(self, bra, **hints):
  349. return KroneckerDelta(self.n, bra.n)
  350. def _apply_operator_SigmaZ(self, op, **options):
  351. if self.n == 0:
  352. return self
  353. else:
  354. return S.NegativeOne * self
  355. def _apply_operator_SigmaX(self, op, **options):
  356. return SigmaZKet(1) if self.n == 0 else SigmaZKet(0)
  357. def _apply_operator_SigmaY(self, op, **options):
  358. return I * SigmaZKet(1) if self.n == 0 else (-I) * SigmaZKet(0)
  359. def _apply_operator_SigmaMinus(self, op, **options):
  360. if self.n == 0:
  361. return SigmaZKet(1)
  362. else:
  363. return S.Zero
  364. def _apply_operator_SigmaPlus(self, op, **options):
  365. if self.n == 0:
  366. return S.Zero
  367. else:
  368. return SigmaZKet(0)
  369. def _represent_default_basis(self, **options):
  370. format = options.get('format', 'sympy')
  371. if format == 'sympy':
  372. return Matrix([[1], [0]]) if self.n == 0 else Matrix([[0], [1]])
  373. else:
  374. raise NotImplementedError('Representation in format ' +
  375. format + ' not implemented.')
  376. class SigmaZBra(Bra):
  377. """Bra for a two-level quantum system.
  378. Parameters
  379. ==========
  380. n : Number
  381. The state number (0 or 1).
  382. """
  383. def __new__(cls, n):
  384. if n not in (0, 1):
  385. raise ValueError("n must be 0 or 1")
  386. return Bra.__new__(cls, n)
  387. @property
  388. def n(self):
  389. return self.label[0]
  390. @classmethod
  391. def dual_class(self):
  392. return SigmaZKet
  393. def _qsimplify_pauli_product(a, b):
  394. """
  395. Internal helper function for simplifying products of Pauli operators.
  396. """
  397. if not (isinstance(a, SigmaOpBase) and isinstance(b, SigmaOpBase)):
  398. return Mul(a, b)
  399. if a.name != b.name:
  400. # Pauli matrices with different labels commute; sort by name
  401. if a.name < b.name:
  402. return Mul(a, b)
  403. else:
  404. return Mul(b, a)
  405. elif isinstance(a, SigmaX):
  406. if isinstance(b, SigmaX):
  407. return S.One
  408. if isinstance(b, SigmaY):
  409. return I * SigmaZ(a.name)
  410. if isinstance(b, SigmaZ):
  411. return - I * SigmaY(a.name)
  412. if isinstance(b, SigmaMinus):
  413. return (S.Half + SigmaZ(a.name)/2)
  414. if isinstance(b, SigmaPlus):
  415. return (S.Half - SigmaZ(a.name)/2)
  416. elif isinstance(a, SigmaY):
  417. if isinstance(b, SigmaX):
  418. return - I * SigmaZ(a.name)
  419. if isinstance(b, SigmaY):
  420. return S.One
  421. if isinstance(b, SigmaZ):
  422. return I * SigmaX(a.name)
  423. if isinstance(b, SigmaMinus):
  424. return -I * (S.One + SigmaZ(a.name))/2
  425. if isinstance(b, SigmaPlus):
  426. return I * (S.One - SigmaZ(a.name))/2
  427. elif isinstance(a, SigmaZ):
  428. if isinstance(b, SigmaX):
  429. return I * SigmaY(a.name)
  430. if isinstance(b, SigmaY):
  431. return - I * SigmaX(a.name)
  432. if isinstance(b, SigmaZ):
  433. return S.One
  434. if isinstance(b, SigmaMinus):
  435. return - SigmaMinus(a.name)
  436. if isinstance(b, SigmaPlus):
  437. return SigmaPlus(a.name)
  438. elif isinstance(a, SigmaMinus):
  439. if isinstance(b, SigmaX):
  440. return (S.One - SigmaZ(a.name))/2
  441. if isinstance(b, SigmaY):
  442. return - I * (S.One - SigmaZ(a.name))/2
  443. if isinstance(b, SigmaZ):
  444. # (SigmaX(a.name) - I * SigmaY(a.name))/2
  445. return SigmaMinus(b.name)
  446. if isinstance(b, SigmaMinus):
  447. return S.Zero
  448. if isinstance(b, SigmaPlus):
  449. return S.Half - SigmaZ(a.name)/2
  450. elif isinstance(a, SigmaPlus):
  451. if isinstance(b, SigmaX):
  452. return (S.One + SigmaZ(a.name))/2
  453. if isinstance(b, SigmaY):
  454. return I * (S.One + SigmaZ(a.name))/2
  455. if isinstance(b, SigmaZ):
  456. #-(SigmaX(a.name) + I * SigmaY(a.name))/2
  457. return -SigmaPlus(a.name)
  458. if isinstance(b, SigmaMinus):
  459. return (S.One + SigmaZ(a.name))/2
  460. if isinstance(b, SigmaPlus):
  461. return S.Zero
  462. else:
  463. return a * b
  464. def qsimplify_pauli(e):
  465. """
  466. Simplify an expression that includes products of pauli operators.
  467. Parameters
  468. ==========
  469. e : expression
  470. An expression that contains products of Pauli operators that is
  471. to be simplified.
  472. Examples
  473. ========
  474. >>> from sympy.physics.quantum.pauli import SigmaX, SigmaY
  475. >>> from sympy.physics.quantum.pauli import qsimplify_pauli
  476. >>> sx, sy = SigmaX(), SigmaY()
  477. >>> sx * sy
  478. SigmaX()*SigmaY()
  479. >>> qsimplify_pauli(sx * sy)
  480. I*SigmaZ()
  481. """
  482. if isinstance(e, Operator):
  483. return e
  484. if isinstance(e, (Add, Pow, exp)):
  485. t = type(e)
  486. return t(*(qsimplify_pauli(arg) for arg in e.args))
  487. if isinstance(e, Mul):
  488. c, nc = e.args_cnc()
  489. nc_s = []
  490. while nc:
  491. curr = nc.pop(0)
  492. while (len(nc) and
  493. isinstance(curr, SigmaOpBase) and
  494. isinstance(nc[0], SigmaOpBase) and
  495. curr.name == nc[0].name):
  496. x = nc.pop(0)
  497. y = _qsimplify_pauli_product(curr, x)
  498. c1, nc1 = y.args_cnc()
  499. curr = Mul(*nc1)
  500. c = c + c1
  501. nc_s.append(curr)
  502. return Mul(*c) * Mul(*nc_s)
  503. return e