Anders and Briegel in Python
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

150 行
4.8KB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Exposes a few basic QI operators
  5. And a circuit-model simulator
  6. """
  7. from __future__ import absolute_import
  8. import numpy as np
  9. import itertools as it
  10. from fractions import Fraction
  11. from six.moves import range
  12. from six.moves import zip
  13. def hermitian_conjugate(u):
  14. """ Shortcut to the Hermitian conjugate """
  15. return np.conjugate(np.transpose(u))
  16. # Constants
  17. ir2 = 1 / np.sqrt(2)
  18. # Operators
  19. id = np.array(np.eye(2, dtype=complex))
  20. px = np.array([[0, 1], [1, 0]], dtype=complex)
  21. py = np.array([[0, -1j], [1j, 0]], dtype=complex)
  22. pz = np.array([[1, 0], [0, -1]], dtype=complex)
  23. ha = hadamard = np.array([[1, 1], [1, -1]], dtype=complex) * ir2
  24. ph = np.array([[1, 0], [0, 1j]], dtype=complex)
  25. t = np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex)
  26. sqx = np.array(
  27. [[1. + 0.j, -0. + 1.j], [-0. + 1.j, 1. - 0.j]], dtype=complex) * ir2
  28. msqx = np.array(
  29. [[1. + 0.j, 0. - 1.j], [0. - 1.j, 1. - 0.j]], dtype=complex) * ir2
  30. sqy = np.array(
  31. [[1. + 0.j, 1. + 0.j], [-1. - 0.j, 1. - 0.j]], dtype=complex) * ir2
  32. msqy = np.array(
  33. [[1. + 0.j, -1. - 0.j], [1. + 0.j, 1. - 0.j]], dtype=complex) * ir2
  34. sqz = np.array(
  35. [[1. + 1.j, 0. + 0.j], [0. + 0.j, 1. - 1.j]], dtype=complex) * ir2
  36. msqz = np.array(
  37. [[1. - 1.j, 0. + 0.j], [0. + 0.j, 1. + 1.j]], dtype=complex) * ir2
  38. # CZ gate
  39. cz = np.array(np.eye(4), dtype=complex)
  40. cz[3, 3] = -1
  41. # States
  42. zero = np.array([[1], [0]], dtype=complex)
  43. one = np.array([[0], [1]], dtype=complex)
  44. plus = np.array([[1], [1]], dtype=complex) / np.sqrt(2)
  45. bond = cz.dot(np.kron(plus, plus))
  46. nobond = np.kron(plus, plus)
  47. # Labelling stuff
  48. common_us = id, px, py, pz, ha, ph, sqz, msqz, sqy, msqy, sqx, msqx
  49. names = "identity", "px", "py", "pz", "hadamard", "phase", "sqz", "msqz", "sqy", "msqy", "sqx", "msqx"
  50. by_name = dict(list(zip(names, common_us)))
  51. paulis = px, py, pz
  52. operators = id, px, py, pz
  53. def normalize_global_phase(m):
  54. """ Normalize the global phase of a matrix """
  55. v = next((x for x in m.flatten() if np.abs(x) > 0.001))
  56. phase = np.arctan2(v.imag, v.real) % np.pi
  57. rot = np.exp(-1j * phase)
  58. return rot * m if rot * v > 0 else -rot * m
  59. class CircuitModel(object):
  60. def __init__(self, nqubits):
  61. self.nqubits = nqubits
  62. self.d = 2 ** nqubits
  63. self.state = np.zeros((self.d, 1), dtype=complex)
  64. self.state[0, 0] = 1
  65. def act_cz(self, control, target):
  66. """ Act a CU somewhere. """
  67. control = 1 << control
  68. target = 1 << target
  69. for i in range(self.d):
  70. if (i & control) and (i & target):
  71. self.state[i, 0] *= -1
  72. def act_cnot(self, control, target):
  73. """ Act a CNOT. """
  74. self.act_hadamard(target)
  75. self.act_cz(control, target)
  76. self.act_hadamard(target)
  77. def act_hadamard(self, qubit):
  78. """ Act a hadamard somewhere. """
  79. where = 1 << qubit
  80. output = np.zeros((self.d, 1), dtype=complex)
  81. for i, v in enumerate(self.state):
  82. q = int(i & where > 0)
  83. output[i] += v * ha[q, q]
  84. output[i ^ where] += v * ha[int(not q), q]
  85. self.state = output
  86. def act_local_rotation(self, qubit, u):
  87. """ Act a local unitary somwhere. """
  88. where = 1 << qubit
  89. output = np.zeros((self.d, 1), dtype=complex)
  90. for i, v in enumerate(self.state):
  91. q = int(i & where > 0)
  92. output[i] += v * u[q, q]
  93. output[i ^ where] += v * u[int(not q), q]
  94. self.state = output
  95. def act_circuit(self, circuit):
  96. """ Act a sequence of gates. """
  97. for node, operation in circuit:
  98. if operation == "cz":
  99. self.act_cz(*node)
  100. else:
  101. self.act_local_rotation(node, operation)
  102. def __eq__(self, other):
  103. """ Check whether two quantum states are the same or not,
  104. up to a global phase. """
  105. a = normalize_global_phase(self.state)
  106. b = normalize_global_phase(other.state)
  107. return np.allclose(a, b)
  108. def __setitem__(self, key, value):
  109. """ Set a matrix element """
  110. self.state[key] = value
  111. def __getitem__(self, key):
  112. """ Get a matrix element """
  113. return self.state[key]
  114. def __str__(self):
  115. s = ""
  116. for i in range(self.d):
  117. label = bin(i)[2:].rjust(self.nqubits, "0")[::-1]
  118. if abs(self.state[i, 0]) > 0.00001:
  119. term = self.state[i, 0]
  120. real_sign = " " if term.real>=0 else "-"
  121. real_frac = Fraction(str(term.real**2)).limit_denominator()
  122. imag_sign = "+" if term.imag>=0 else "-"
  123. imag_frac = Fraction(str(term.imag**2)).limit_denominator()
  124. s += "|{}❭: \t{}√{}\t{} i √{}\n".format(
  125. label, real_sign, real_frac, imag_sign, imag_frac)
  126. return s