test_circuitutils.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. from sympy.core.mul import Mul
  2. from sympy.core.numbers import Integer
  3. from sympy.core.symbol import Symbol
  4. from sympy.utilities import numbered_symbols
  5. from sympy.physics.quantum.gate import X, Y, Z, H, CNOT, CGate
  6. from sympy.physics.quantum.identitysearch import bfs_identity_search
  7. from sympy.physics.quantum.circuitutils import (kmp_table, find_subcircuit,
  8. replace_subcircuit, convert_to_symbolic_indices,
  9. convert_to_real_indices, random_reduce, random_insert,
  10. flatten_ids)
  11. from sympy.testing.pytest import slow
  12. def create_gate_sequence(qubit=0):
  13. gates = (X(qubit), Y(qubit), Z(qubit), H(qubit))
  14. return gates
  15. def test_kmp_table():
  16. word = ('a', 'b', 'c', 'd', 'a', 'b', 'd')
  17. expected_table = [-1, 0, 0, 0, 0, 1, 2]
  18. assert expected_table == kmp_table(word)
  19. word = ('P', 'A', 'R', 'T', 'I', 'C', 'I', 'P', 'A', 'T', 'E', ' ',
  20. 'I', 'N', ' ', 'P', 'A', 'R', 'A', 'C', 'H', 'U', 'T', 'E')
  21. expected_table = [-1, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0,
  22. 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0]
  23. assert expected_table == kmp_table(word)
  24. x = X(0)
  25. y = Y(0)
  26. z = Z(0)
  27. h = H(0)
  28. word = (x, y, y, x, z)
  29. expected_table = [-1, 0, 0, 0, 1]
  30. assert expected_table == kmp_table(word)
  31. word = (x, x, y, h, z)
  32. expected_table = [-1, 0, 1, 0, 0]
  33. assert expected_table == kmp_table(word)
  34. def test_find_subcircuit():
  35. x = X(0)
  36. y = Y(0)
  37. z = Z(0)
  38. h = H(0)
  39. x1 = X(1)
  40. y1 = Y(1)
  41. i0 = Symbol('i0')
  42. x_i0 = X(i0)
  43. y_i0 = Y(i0)
  44. z_i0 = Z(i0)
  45. h_i0 = H(i0)
  46. circuit = (x, y, z)
  47. assert find_subcircuit(circuit, (x,)) == 0
  48. assert find_subcircuit(circuit, (x1,)) == -1
  49. assert find_subcircuit(circuit, (y,)) == 1
  50. assert find_subcircuit(circuit, (h,)) == -1
  51. assert find_subcircuit(circuit, Mul(x, h)) == -1
  52. assert find_subcircuit(circuit, Mul(x, y, z)) == 0
  53. assert find_subcircuit(circuit, Mul(y, z)) == 1
  54. assert find_subcircuit(Mul(*circuit), (x, y, z, h)) == -1
  55. assert find_subcircuit(Mul(*circuit), (z, y, x)) == -1
  56. assert find_subcircuit(circuit, (x,), start=2, end=1) == -1
  57. circuit = (x, y, x, y, z)
  58. assert find_subcircuit(Mul(*circuit), Mul(x, y, z)) == 2
  59. assert find_subcircuit(circuit, (x,), start=1) == 2
  60. assert find_subcircuit(circuit, (x, y), start=1, end=2) == -1
  61. assert find_subcircuit(Mul(*circuit), (x, y), start=1, end=3) == -1
  62. assert find_subcircuit(circuit, (x, y), start=1, end=4) == 2
  63. assert find_subcircuit(circuit, (x, y), start=2, end=4) == 2
  64. circuit = (x, y, z, x1, x, y, z, h, x, y, x1,
  65. x, y, z, h, y1, h)
  66. assert find_subcircuit(circuit, (x, y, z, h, y1)) == 11
  67. circuit = (x, y, x_i0, y_i0, z_i0, z)
  68. assert find_subcircuit(circuit, (x_i0, y_i0, z_i0)) == 2
  69. circuit = (x_i0, y_i0, z_i0, x_i0, y_i0, h_i0)
  70. subcircuit = (x_i0, y_i0, z_i0)
  71. result = find_subcircuit(circuit, subcircuit)
  72. assert result == 0
  73. def test_replace_subcircuit():
  74. x = X(0)
  75. y = Y(0)
  76. z = Z(0)
  77. h = H(0)
  78. cnot = CNOT(1, 0)
  79. cgate_z = CGate((0,), Z(1))
  80. # Standard cases
  81. circuit = (z, y, x, x)
  82. remove = (z, y, x)
  83. assert replace_subcircuit(circuit, Mul(*remove)) == (x,)
  84. assert replace_subcircuit(circuit, remove + (x,)) == ()
  85. assert replace_subcircuit(circuit, remove, pos=1) == circuit
  86. assert replace_subcircuit(circuit, remove, pos=0) == (x,)
  87. assert replace_subcircuit(circuit, (x, x), pos=2) == (z, y)
  88. assert replace_subcircuit(circuit, (h,)) == circuit
  89. circuit = (x, y, x, y, z)
  90. remove = (x, y, z)
  91. assert replace_subcircuit(Mul(*circuit), Mul(*remove)) == (x, y)
  92. remove = (x, y, x, y)
  93. assert replace_subcircuit(circuit, remove) == (z,)
  94. circuit = (x, h, cgate_z, h, cnot)
  95. remove = (x, h, cgate_z)
  96. assert replace_subcircuit(circuit, Mul(*remove), pos=-1) == (h, cnot)
  97. assert replace_subcircuit(circuit, remove, pos=1) == circuit
  98. remove = (h, h)
  99. assert replace_subcircuit(circuit, remove) == circuit
  100. remove = (h, cgate_z, h, cnot)
  101. assert replace_subcircuit(circuit, remove) == (x,)
  102. replace = (h, x)
  103. actual = replace_subcircuit(circuit, remove,
  104. replace=replace)
  105. assert actual == (x, h, x)
  106. circuit = (x, y, h, x, y, z)
  107. remove = (x, y)
  108. replace = (cnot, cgate_z)
  109. actual = replace_subcircuit(circuit, remove,
  110. replace=Mul(*replace))
  111. assert actual == (cnot, cgate_z, h, x, y, z)
  112. actual = replace_subcircuit(circuit, remove,
  113. replace=replace, pos=1)
  114. assert actual == (x, y, h, cnot, cgate_z, z)
  115. def test_convert_to_symbolic_indices():
  116. (x, y, z, h) = create_gate_sequence()
  117. i0 = Symbol('i0')
  118. exp_map = {i0: Integer(0)}
  119. actual, act_map, sndx, gen = convert_to_symbolic_indices((x,))
  120. assert actual == (X(i0),)
  121. assert act_map == exp_map
  122. expected = (X(i0), Y(i0), Z(i0), H(i0))
  123. exp_map = {i0: Integer(0)}
  124. actual, act_map, sndx, gen = convert_to_symbolic_indices((x, y, z, h))
  125. assert actual == expected
  126. assert exp_map == act_map
  127. (x1, y1, z1, h1) = create_gate_sequence(1)
  128. i1 = Symbol('i1')
  129. expected = (X(i0), Y(i0), Z(i0), H(i0))
  130. exp_map = {i0: Integer(1)}
  131. actual, act_map, sndx, gen = convert_to_symbolic_indices((x1, y1, z1, h1))
  132. assert actual == expected
  133. assert act_map == exp_map
  134. expected = (X(i0), Y(i0), Z(i0), H(i0), X(i1), Y(i1), Z(i1), H(i1))
  135. exp_map = {i0: Integer(0), i1: Integer(1)}
  136. actual, act_map, sndx, gen = convert_to_symbolic_indices((x, y, z, h,
  137. x1, y1, z1, h1))
  138. assert actual == expected
  139. assert act_map == exp_map
  140. exp_map = {i0: Integer(1), i1: Integer(0)}
  141. actual, act_map, sndx, gen = convert_to_symbolic_indices(Mul(x1, y1,
  142. z1, h1, x, y, z, h))
  143. assert actual == expected
  144. assert act_map == exp_map
  145. expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1), H(i0), H(i1))
  146. exp_map = {i0: Integer(0), i1: Integer(1)}
  147. actual, act_map, sndx, gen = convert_to_symbolic_indices(Mul(x, x1,
  148. y, y1, z, z1, h, h1))
  149. assert actual == expected
  150. assert act_map == exp_map
  151. exp_map = {i0: Integer(1), i1: Integer(0)}
  152. actual, act_map, sndx, gen = convert_to_symbolic_indices((x1, x, y1, y,
  153. z1, z, h1, h))
  154. assert actual == expected
  155. assert act_map == exp_map
  156. cnot_10 = CNOT(1, 0)
  157. cnot_01 = CNOT(0, 1)
  158. cgate_z_10 = CGate(1, Z(0))
  159. cgate_z_01 = CGate(0, Z(1))
  160. expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1),
  161. H(i0), H(i1), CNOT(i1, i0), CNOT(i0, i1),
  162. CGate(i1, Z(i0)), CGate(i0, Z(i1)))
  163. exp_map = {i0: Integer(0), i1: Integer(1)}
  164. args = (x, x1, y, y1, z, z1, h, h1, cnot_10, cnot_01,
  165. cgate_z_10, cgate_z_01)
  166. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  167. assert actual == expected
  168. assert act_map == exp_map
  169. args = (x1, x, y1, y, z1, z, h1, h, cnot_10, cnot_01,
  170. cgate_z_10, cgate_z_01)
  171. expected = (X(i0), X(i1), Y(i0), Y(i1), Z(i0), Z(i1),
  172. H(i0), H(i1), CNOT(i0, i1), CNOT(i1, i0),
  173. CGate(i0, Z(i1)), CGate(i1, Z(i0)))
  174. exp_map = {i0: Integer(1), i1: Integer(0)}
  175. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  176. assert actual == expected
  177. assert act_map == exp_map
  178. args = (cnot_10, h, cgate_z_01, h)
  179. expected = (CNOT(i0, i1), H(i1), CGate(i1, Z(i0)), H(i1))
  180. exp_map = {i0: Integer(1), i1: Integer(0)}
  181. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  182. assert actual == expected
  183. assert act_map == exp_map
  184. args = (cnot_01, h1, cgate_z_10, h1)
  185. exp_map = {i0: Integer(0), i1: Integer(1)}
  186. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  187. assert actual == expected
  188. assert act_map == exp_map
  189. args = (cnot_10, h1, cgate_z_01, h1)
  190. expected = (CNOT(i0, i1), H(i0), CGate(i1, Z(i0)), H(i0))
  191. exp_map = {i0: Integer(1), i1: Integer(0)}
  192. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  193. assert actual == expected
  194. assert act_map == exp_map
  195. i2 = Symbol('i2')
  196. ccgate_z = CGate(0, CGate(1, Z(2)))
  197. ccgate_x = CGate(1, CGate(2, X(0)))
  198. args = (ccgate_z, ccgate_x)
  199. expected = (CGate(i0, CGate(i1, Z(i2))), CGate(i1, CGate(i2, X(i0))))
  200. exp_map = {i0: Integer(0), i1: Integer(1), i2: Integer(2)}
  201. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  202. assert actual == expected
  203. assert act_map == exp_map
  204. ndx_map = {i0: Integer(0)}
  205. index_gen = numbered_symbols(prefix='i', start=1)
  206. actual, act_map, sndx, gen = convert_to_symbolic_indices(args,
  207. qubit_map=ndx_map,
  208. start=i0,
  209. gen=index_gen)
  210. assert actual == expected
  211. assert act_map == exp_map
  212. i3 = Symbol('i3')
  213. cgate_x0_c321 = CGate((3, 2, 1), X(0))
  214. exp_map = {i0: Integer(3), i1: Integer(2),
  215. i2: Integer(1), i3: Integer(0)}
  216. expected = (CGate((i0, i1, i2), X(i3)),)
  217. args = (cgate_x0_c321,)
  218. actual, act_map, sndx, gen = convert_to_symbolic_indices(args)
  219. assert actual == expected
  220. assert act_map == exp_map
  221. def test_convert_to_real_indices():
  222. i0 = Symbol('i0')
  223. i1 = Symbol('i1')
  224. (x, y, z, h) = create_gate_sequence()
  225. x_i0 = X(i0)
  226. y_i0 = Y(i0)
  227. z_i0 = Z(i0)
  228. qubit_map = {i0: 0}
  229. args = (z_i0, y_i0, x_i0)
  230. expected = (z, y, x)
  231. actual = convert_to_real_indices(args, qubit_map)
  232. assert actual == expected
  233. cnot_10 = CNOT(1, 0)
  234. cnot_01 = CNOT(0, 1)
  235. cgate_z_10 = CGate(1, Z(0))
  236. cgate_z_01 = CGate(0, Z(1))
  237. cnot_i1_i0 = CNOT(i1, i0)
  238. cnot_i0_i1 = CNOT(i0, i1)
  239. cgate_z_i1_i0 = CGate(i1, Z(i0))
  240. qubit_map = {i0: 0, i1: 1}
  241. args = (cnot_i1_i0,)
  242. expected = (cnot_10,)
  243. actual = convert_to_real_indices(args, qubit_map)
  244. assert actual == expected
  245. args = (cgate_z_i1_i0,)
  246. expected = (cgate_z_10,)
  247. actual = convert_to_real_indices(args, qubit_map)
  248. assert actual == expected
  249. args = (cnot_i0_i1,)
  250. expected = (cnot_01,)
  251. actual = convert_to_real_indices(args, qubit_map)
  252. assert actual == expected
  253. qubit_map = {i0: 1, i1: 0}
  254. args = (cgate_z_i1_i0,)
  255. expected = (cgate_z_01,)
  256. actual = convert_to_real_indices(args, qubit_map)
  257. assert actual == expected
  258. i2 = Symbol('i2')
  259. ccgate_z = CGate(i0, CGate(i1, Z(i2)))
  260. ccgate_x = CGate(i1, CGate(i2, X(i0)))
  261. qubit_map = {i0: 0, i1: 1, i2: 2}
  262. args = (ccgate_z, ccgate_x)
  263. expected = (CGate(0, CGate(1, Z(2))), CGate(1, CGate(2, X(0))))
  264. actual = convert_to_real_indices(Mul(*args), qubit_map)
  265. assert actual == expected
  266. qubit_map = {i0: 1, i2: 0, i1: 2}
  267. args = (ccgate_x, ccgate_z)
  268. expected = (CGate(2, CGate(0, X(1))), CGate(1, CGate(2, Z(0))))
  269. actual = convert_to_real_indices(args, qubit_map)
  270. assert actual == expected
  271. @slow
  272. def test_random_reduce():
  273. x = X(0)
  274. y = Y(0)
  275. z = Z(0)
  276. h = H(0)
  277. cnot = CNOT(1, 0)
  278. cgate_z = CGate((0,), Z(1))
  279. gate_list = [x, y, z]
  280. ids = list(bfs_identity_search(gate_list, 1, max_depth=4))
  281. circuit = (x, y, h, z, cnot)
  282. assert random_reduce(circuit, []) == circuit
  283. assert random_reduce(circuit, ids) == circuit
  284. seq = [2, 11, 9, 3, 5]
  285. circuit = (x, y, z, x, y, h)
  286. assert random_reduce(circuit, ids, seed=seq) == (x, y, h)
  287. circuit = (x, x, y, y, z, z)
  288. assert random_reduce(circuit, ids, seed=seq) == (x, x, y, y)
  289. seq = [14, 13, 0]
  290. assert random_reduce(circuit, ids, seed=seq) == (y, y, z, z)
  291. gate_list = [x, y, z, h, cnot, cgate_z]
  292. ids = list(bfs_identity_search(gate_list, 2, max_depth=4))
  293. seq = [25]
  294. circuit = (x, y, z, y, h, y, h, cgate_z, h, cnot)
  295. expected = (x, y, z, cgate_z, h, cnot)
  296. assert random_reduce(circuit, ids, seed=seq) == expected
  297. circuit = Mul(*circuit)
  298. assert random_reduce(circuit, ids, seed=seq) == expected
  299. @slow
  300. def test_random_insert():
  301. x = X(0)
  302. y = Y(0)
  303. z = Z(0)
  304. h = H(0)
  305. cnot = CNOT(1, 0)
  306. cgate_z = CGate((0,), Z(1))
  307. choices = [(x, x)]
  308. circuit = (y, y)
  309. loc, choice = 0, 0
  310. actual = random_insert(circuit, choices, seed=[loc, choice])
  311. assert actual == (x, x, y, y)
  312. circuit = (x, y, z, h)
  313. choices = [(h, h), (x, y, z)]
  314. expected = (x, x, y, z, y, z, h)
  315. loc, choice = 1, 1
  316. actual = random_insert(circuit, choices, seed=[loc, choice])
  317. assert actual == expected
  318. gate_list = [x, y, z, h, cnot, cgate_z]
  319. ids = list(bfs_identity_search(gate_list, 2, max_depth=4))
  320. eq_ids = flatten_ids(ids)
  321. circuit = (x, y, h, cnot, cgate_z)
  322. expected = (x, z, x, z, x, y, h, cnot, cgate_z)
  323. loc, choice = 1, 30
  324. actual = random_insert(circuit, eq_ids, seed=[loc, choice])
  325. assert actual == expected
  326. circuit = Mul(*circuit)
  327. actual = random_insert(circuit, eq_ids, seed=[loc, choice])
  328. assert actual == expected