test_gate.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. from sympy.core.mul import Mul
  2. from sympy.core.numbers import (I, Integer, Rational, pi)
  3. from sympy.core.symbol import (Wild, symbols)
  4. from sympy.functions.elementary.exponential import exp
  5. from sympy.functions.elementary.miscellaneous import sqrt
  6. from sympy.matrices import Matrix, ImmutableMatrix
  7. from sympy.physics.quantum.gate import (XGate, YGate, ZGate, random_circuit,
  8. CNOT, IdentityGate, H, X, Y, S, T, Z, SwapGate, gate_simp, gate_sort,
  9. CNotGate, TGate, HadamardGate, PhaseGate, UGate, CGate)
  10. from sympy.physics.quantum.commutator import Commutator
  11. from sympy.physics.quantum.anticommutator import AntiCommutator
  12. from sympy.physics.quantum.represent import represent
  13. from sympy.physics.quantum.qapply import qapply
  14. from sympy.physics.quantum.qubit import Qubit, IntQubit, qubit_to_matrix, \
  15. matrix_to_qubit
  16. from sympy.physics.quantum.matrixutils import matrix_to_zero
  17. from sympy.physics.quantum.matrixcache import sqrt2_inv
  18. from sympy.physics.quantum import Dagger
  19. def test_gate():
  20. """Test a basic gate."""
  21. h = HadamardGate(1)
  22. assert h.min_qubits == 2
  23. assert h.nqubits == 1
  24. i0 = Wild('i0')
  25. i1 = Wild('i1')
  26. h0_w1 = HadamardGate(i0)
  27. h0_w2 = HadamardGate(i0)
  28. h1_w1 = HadamardGate(i1)
  29. assert h0_w1 == h0_w2
  30. assert h0_w1 != h1_w1
  31. assert h1_w1 != h0_w2
  32. cnot_10_w1 = CNOT(i1, i0)
  33. cnot_10_w2 = CNOT(i1, i0)
  34. cnot_01_w1 = CNOT(i0, i1)
  35. assert cnot_10_w1 == cnot_10_w2
  36. assert cnot_10_w1 != cnot_01_w1
  37. assert cnot_10_w2 != cnot_01_w1
  38. def test_UGate():
  39. a, b, c, d = symbols('a,b,c,d')
  40. uMat = Matrix([[a, b], [c, d]])
  41. # Test basic case where gate exists in 1-qubit space
  42. u1 = UGate((0,), uMat)
  43. assert represent(u1, nqubits=1) == uMat
  44. assert qapply(u1*Qubit('0')) == a*Qubit('0') + c*Qubit('1')
  45. assert qapply(u1*Qubit('1')) == b*Qubit('0') + d*Qubit('1')
  46. # Test case where gate exists in a larger space
  47. u2 = UGate((1,), uMat)
  48. u2Rep = represent(u2, nqubits=2)
  49. for i in range(4):
  50. assert u2Rep*qubit_to_matrix(IntQubit(i, 2)) == \
  51. qubit_to_matrix(qapply(u2*IntQubit(i, 2)))
  52. def test_cgate():
  53. """Test the general CGate."""
  54. # Test single control functionality
  55. CNOTMatrix = Matrix(
  56. [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
  57. assert represent(CGate(1, XGate(0)), nqubits=2) == CNOTMatrix
  58. # Test multiple control bit functionality
  59. ToffoliGate = CGate((1, 2), XGate(0))
  60. assert represent(ToffoliGate, nqubits=3) == \
  61. Matrix(
  62. [[1, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0],
  63. [0, 0, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0,
  64. 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 1],
  65. [0, 0, 0, 0, 0, 0, 1, 0]])
  66. ToffoliGate = CGate((3, 0), XGate(1))
  67. assert qapply(ToffoliGate*Qubit('1001')) == \
  68. matrix_to_qubit(represent(ToffoliGate*Qubit('1001'), nqubits=4))
  69. assert qapply(ToffoliGate*Qubit('0000')) == \
  70. matrix_to_qubit(represent(ToffoliGate*Qubit('0000'), nqubits=4))
  71. CYGate = CGate(1, YGate(0))
  72. CYGate_matrix = Matrix(
  73. ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 0, -I), (0, 0, I, 0)))
  74. # Test 2 qubit controlled-Y gate decompose method.
  75. assert represent(CYGate.decompose(), nqubits=2) == CYGate_matrix
  76. CZGate = CGate(0, ZGate(1))
  77. CZGate_matrix = Matrix(
  78. ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, -1)))
  79. assert qapply(CZGate*Qubit('11')) == -Qubit('11')
  80. assert matrix_to_qubit(represent(CZGate*Qubit('11'), nqubits=2)) == \
  81. -Qubit('11')
  82. # Test 2 qubit controlled-Z gate decompose method.
  83. assert represent(CZGate.decompose(), nqubits=2) == CZGate_matrix
  84. CPhaseGate = CGate(0, PhaseGate(1))
  85. assert qapply(CPhaseGate*Qubit('11')) == \
  86. I*Qubit('11')
  87. assert matrix_to_qubit(represent(CPhaseGate*Qubit('11'), nqubits=2)) == \
  88. I*Qubit('11')
  89. # Test that the dagger, inverse, and power of CGate is evaluated properly
  90. assert Dagger(CZGate) == CZGate
  91. assert pow(CZGate, 1) == Dagger(CZGate)
  92. assert Dagger(CZGate) == CZGate.inverse()
  93. assert Dagger(CPhaseGate) != CPhaseGate
  94. assert Dagger(CPhaseGate) == CPhaseGate.inverse()
  95. assert Dagger(CPhaseGate) == pow(CPhaseGate, -1)
  96. assert pow(CPhaseGate, -1) == CPhaseGate.inverse()
  97. def test_UGate_CGate_combo():
  98. a, b, c, d = symbols('a,b,c,d')
  99. uMat = Matrix([[a, b], [c, d]])
  100. cMat = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, a, b], [0, 0, c, d]])
  101. # Test basic case where gate exists in 1-qubit space.
  102. u1 = UGate((0,), uMat)
  103. cu1 = CGate(1, u1)
  104. assert represent(cu1, nqubits=2) == cMat
  105. assert qapply(cu1*Qubit('10')) == a*Qubit('10') + c*Qubit('11')
  106. assert qapply(cu1*Qubit('11')) == b*Qubit('10') + d*Qubit('11')
  107. assert qapply(cu1*Qubit('01')) == Qubit('01')
  108. assert qapply(cu1*Qubit('00')) == Qubit('00')
  109. # Test case where gate exists in a larger space.
  110. u2 = UGate((1,), uMat)
  111. u2Rep = represent(u2, nqubits=2)
  112. for i in range(4):
  113. assert u2Rep*qubit_to_matrix(IntQubit(i, 2)) == \
  114. qubit_to_matrix(qapply(u2*IntQubit(i, 2)))
  115. def test_UGate_OneQubitGate_combo():
  116. v, w, f, g = symbols('v w f g')
  117. uMat1 = ImmutableMatrix([[v, w], [f, g]])
  118. cMat1 = Matrix([[v, w + 1, 0, 0], [f + 1, g, 0, 0], [0, 0, v, w + 1], [0, 0, f + 1, g]])
  119. u1 = X(0) + UGate(0, uMat1)
  120. assert represent(u1, nqubits=2) == cMat1
  121. uMat2 = ImmutableMatrix([[1/sqrt(2), 1/sqrt(2)], [I/sqrt(2), -I/sqrt(2)]])
  122. cMat2_1 = Matrix([[Rational(1, 2) + I/2, Rational(1, 2) - I/2],
  123. [Rational(1, 2) - I/2, Rational(1, 2) + I/2]])
  124. cMat2_2 = Matrix([[1, 0], [0, I]])
  125. u2 = UGate(0, uMat2)
  126. assert represent(H(0)*u2, nqubits=1) == cMat2_1
  127. assert represent(u2*H(0), nqubits=1) == cMat2_2
  128. def test_represent_hadamard():
  129. """Test the representation of the hadamard gate."""
  130. circuit = HadamardGate(0)*Qubit('00')
  131. answer = represent(circuit, nqubits=2)
  132. # Check that the answers are same to within an epsilon.
  133. assert answer == Matrix([sqrt2_inv, sqrt2_inv, 0, 0])
  134. def test_represent_xgate():
  135. """Test the representation of the X gate."""
  136. circuit = XGate(0)*Qubit('00')
  137. answer = represent(circuit, nqubits=2)
  138. assert Matrix([0, 1, 0, 0]) == answer
  139. def test_represent_ygate():
  140. """Test the representation of the Y gate."""
  141. circuit = YGate(0)*Qubit('00')
  142. answer = represent(circuit, nqubits=2)
  143. assert answer[0] == 0 and answer[1] == I and \
  144. answer[2] == 0 and answer[3] == 0
  145. def test_represent_zgate():
  146. """Test the representation of the Z gate."""
  147. circuit = ZGate(0)*Qubit('00')
  148. answer = represent(circuit, nqubits=2)
  149. assert Matrix([1, 0, 0, 0]) == answer
  150. def test_represent_phasegate():
  151. """Test the representation of the S gate."""
  152. circuit = PhaseGate(0)*Qubit('01')
  153. answer = represent(circuit, nqubits=2)
  154. assert Matrix([0, I, 0, 0]) == answer
  155. def test_represent_tgate():
  156. """Test the representation of the T gate."""
  157. circuit = TGate(0)*Qubit('01')
  158. assert Matrix([0, exp(I*pi/4), 0, 0]) == represent(circuit, nqubits=2)
  159. def test_compound_gates():
  160. """Test a compound gate representation."""
  161. circuit = YGate(0)*ZGate(0)*XGate(0)*HadamardGate(0)*Qubit('00')
  162. answer = represent(circuit, nqubits=2)
  163. assert Matrix([I/sqrt(2), I/sqrt(2), 0, 0]) == answer
  164. def test_cnot_gate():
  165. """Test the CNOT gate."""
  166. circuit = CNotGate(1, 0)
  167. assert represent(circuit, nqubits=2) == \
  168. Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
  169. circuit = circuit*Qubit('111')
  170. assert matrix_to_qubit(represent(circuit, nqubits=3)) == \
  171. qapply(circuit)
  172. circuit = CNotGate(1, 0)
  173. assert Dagger(circuit) == circuit
  174. assert Dagger(Dagger(circuit)) == circuit
  175. assert circuit*circuit == 1
  176. def test_gate_sort():
  177. """Test gate_sort."""
  178. for g in (X, Y, Z, H, S, T):
  179. assert gate_sort(g(2)*g(1)*g(0)) == g(0)*g(1)*g(2)
  180. e = gate_sort(X(1)*H(0)**2*CNOT(0, 1)*X(1)*X(0))
  181. assert e == H(0)**2*CNOT(0, 1)*X(0)*X(1)**2
  182. assert gate_sort(Z(0)*X(0)) == -X(0)*Z(0)
  183. assert gate_sort(Z(0)*X(0)**2) == X(0)**2*Z(0)
  184. assert gate_sort(Y(0)*H(0)) == -H(0)*Y(0)
  185. assert gate_sort(Y(0)*X(0)) == -X(0)*Y(0)
  186. assert gate_sort(Z(0)*Y(0)) == -Y(0)*Z(0)
  187. assert gate_sort(T(0)*S(0)) == S(0)*T(0)
  188. assert gate_sort(Z(0)*S(0)) == S(0)*Z(0)
  189. assert gate_sort(Z(0)*T(0)) == T(0)*Z(0)
  190. assert gate_sort(Z(0)*CNOT(0, 1)) == CNOT(0, 1)*Z(0)
  191. assert gate_sort(S(0)*CNOT(0, 1)) == CNOT(0, 1)*S(0)
  192. assert gate_sort(T(0)*CNOT(0, 1)) == CNOT(0, 1)*T(0)
  193. assert gate_sort(X(1)*CNOT(0, 1)) == CNOT(0, 1)*X(1)
  194. # This takes a long time and should only be uncommented once in a while.
  195. # nqubits = 5
  196. # ngates = 10
  197. # trials = 10
  198. # for i in range(trials):
  199. # c = random_circuit(ngates, nqubits)
  200. # assert represent(c, nqubits=nqubits) == \
  201. # represent(gate_sort(c), nqubits=nqubits)
  202. def test_gate_simp():
  203. """Test gate_simp."""
  204. e = H(0)*X(1)*H(0)**2*CNOT(0, 1)*X(1)**3*X(0)*Z(3)**2*S(4)**3
  205. assert gate_simp(e) == H(0)*CNOT(0, 1)*S(4)*X(0)*Z(4)
  206. assert gate_simp(X(0)*X(0)) == 1
  207. assert gate_simp(Y(0)*Y(0)) == 1
  208. assert gate_simp(Z(0)*Z(0)) == 1
  209. assert gate_simp(H(0)*H(0)) == 1
  210. assert gate_simp(T(0)*T(0)) == S(0)
  211. assert gate_simp(S(0)*S(0)) == Z(0)
  212. assert gate_simp(Integer(1)) == Integer(1)
  213. assert gate_simp(X(0)**2 + Y(0)**2) == Integer(2)
  214. def test_swap_gate():
  215. """Test the SWAP gate."""
  216. swap_gate_matrix = Matrix(
  217. ((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0), (0, 0, 0, 1)))
  218. assert represent(SwapGate(1, 0).decompose(), nqubits=2) == swap_gate_matrix
  219. assert qapply(SwapGate(1, 3)*Qubit('0010')) == Qubit('1000')
  220. nqubits = 4
  221. for i in range(nqubits):
  222. for j in range(i):
  223. assert represent(SwapGate(i, j), nqubits=nqubits) == \
  224. represent(SwapGate(i, j).decompose(), nqubits=nqubits)
  225. def test_one_qubit_commutators():
  226. """Test single qubit gate commutation relations."""
  227. for g1 in (IdentityGate, X, Y, Z, H, T, S):
  228. for g2 in (IdentityGate, X, Y, Z, H, T, S):
  229. e = Commutator(g1(0), g2(0))
  230. a = matrix_to_zero(represent(e, nqubits=1, format='sympy'))
  231. b = matrix_to_zero(represent(e.doit(), nqubits=1, format='sympy'))
  232. assert a == b
  233. e = Commutator(g1(0), g2(1))
  234. assert e.doit() == 0
  235. def test_one_qubit_anticommutators():
  236. """Test single qubit gate anticommutation relations."""
  237. for g1 in (IdentityGate, X, Y, Z, H):
  238. for g2 in (IdentityGate, X, Y, Z, H):
  239. e = AntiCommutator(g1(0), g2(0))
  240. a = matrix_to_zero(represent(e, nqubits=1, format='sympy'))
  241. b = matrix_to_zero(represent(e.doit(), nqubits=1, format='sympy'))
  242. assert a == b
  243. e = AntiCommutator(g1(0), g2(1))
  244. a = matrix_to_zero(represent(e, nqubits=2, format='sympy'))
  245. b = matrix_to_zero(represent(e.doit(), nqubits=2, format='sympy'))
  246. assert a == b
  247. def test_cnot_commutators():
  248. """Test commutators of involving CNOT gates."""
  249. assert Commutator(CNOT(0, 1), Z(0)).doit() == 0
  250. assert Commutator(CNOT(0, 1), T(0)).doit() == 0
  251. assert Commutator(CNOT(0, 1), S(0)).doit() == 0
  252. assert Commutator(CNOT(0, 1), X(1)).doit() == 0
  253. assert Commutator(CNOT(0, 1), CNOT(0, 1)).doit() == 0
  254. assert Commutator(CNOT(0, 1), CNOT(0, 2)).doit() == 0
  255. assert Commutator(CNOT(0, 2), CNOT(0, 1)).doit() == 0
  256. assert Commutator(CNOT(1, 2), CNOT(1, 0)).doit() == 0
  257. def test_random_circuit():
  258. c = random_circuit(10, 3)
  259. assert isinstance(c, Mul)
  260. m = represent(c, nqubits=3)
  261. assert m.shape == (8, 8)
  262. assert isinstance(m, Matrix)
  263. def test_hermitian_XGate():
  264. x = XGate(1, 2)
  265. x_dagger = Dagger(x)
  266. assert (x == x_dagger)
  267. def test_hermitian_YGate():
  268. y = YGate(1, 2)
  269. y_dagger = Dagger(y)
  270. assert (y == y_dagger)
  271. def test_hermitian_ZGate():
  272. z = ZGate(1, 2)
  273. z_dagger = Dagger(z)
  274. assert (z == z_dagger)
  275. def test_unitary_XGate():
  276. x = XGate(1, 2)
  277. x_dagger = Dagger(x)
  278. assert (x*x_dagger == 1)
  279. def test_unitary_YGate():
  280. y = YGate(1, 2)
  281. y_dagger = Dagger(y)
  282. assert (y*y_dagger == 1)
  283. def test_unitary_ZGate():
  284. z = ZGate(1, 2)
  285. z_dagger = Dagger(z)
  286. assert (z*z_dagger == 1)