Anders and Briegel in Python
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.

106 lines
3.4KB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. This program generates lookup tables
  5. """
  6. import qi
  7. import numpy as np
  8. from tqdm import tqdm
  9. from functools import reduce
  10. import itertools as it
  11. DECOMPOSITIONS = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz",
  12. "xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x",
  13. "zzzx", "xxzx", "zx", "zxxx", "xxxz", "xzzz", "xz", "xzxx")
  14. def find_clifford(needle, haystack):
  15. """ Find the index of a given u within a list of unitaries, up to a global phase """
  16. for i, t in enumerate(haystack):
  17. for phase in range(8):
  18. if np.allclose(t, np.exp(1j * phase * np.pi / 4.) * needle):
  19. return i
  20. raise IndexError
  21. def find_cz(bond, c1, c2, z, krontable):
  22. """ Find the output of a CZ operation """
  23. # Figure out the target state
  24. state = qi.bond if bond else qi.nobond
  25. target = qi.cz.dot(krontable[c1, c2].dot(state))
  26. # Choose the sets to search over
  27. s1 = z if c1 in z else xrange(24)
  28. s2 = z if c2 in z else xrange(24)
  29. # Find a match
  30. for bond, c1p, c2p in it.product([0, 1], s1, s2):
  31. state = qi.bond if bond else qi.nobond
  32. trial = krontable[c1p, c2p].dot(state)
  33. for phase in range(8):
  34. if np.allclose(target, np.exp(1j * phase * np.pi / 4.) * trial):
  35. return bond, c1p, c2p
  36. # Didn't find anything - this should never happen
  37. raise IndexError
  38. def compose_u(decomposition):
  39. """ Get the unitary representation of a particular decomposition """
  40. matrices = ({"x": qi.sqx, "z": qi.msqz}[c] for c in decomposition)
  41. return reduce(np.dot, matrices, np.matrix(np.eye(2, dtype=complex)))
  42. def get_unitaries(decompositions):
  43. """ The Clifford group """
  44. return [compose_u(d) for d in decompositions]
  45. def hermitian_conjugate(u):
  46. """ Get the hermitian conjugate """
  47. return np.conjugate(np.transpose(u))
  48. def get_conjugation_table(unitaries):
  49. """ Construct the conjugation table """
  50. return np.array([find_clifford(hermitian_conjugate(u), unitaries) for u in unitaries])
  51. def get_times_table(unitaries):
  52. """ Construct the times-table """
  53. return np.array([[find_clifford(u.dot(v), unitaries) for v in unitaries]
  54. for u in tqdm(unitaries)])
  55. def get_krontable():
  56. """ Cache a table of Kronecker products to speed up a little bit """
  57. krontable = np.zeros((24, 24, 4, 4), dtype=complex)
  58. for i, j in it.product(range(24), range(24)):
  59. krontable[i, j,:,:] = np.kron(unitaries[i], unitaries[j])
  60. return krontable
  61. def get_cz_table(unitaries):
  62. """ Compute the lookup table for the CZ (A&B eq. 9) """
  63. z = (qi.id, qi.px, qi.pz, qi.ph, hermitian_conjugate(qi.ph))
  64. z = [find_clifford(u, unitaries) for u in z]
  65. krontable = get_krontable()
  66. cz_table = np.zeros((2, 24, 24, 3))
  67. for bond, c1, c2 in tqdm(list(it.product([0, 1], range(24), range(24)))):
  68. cz_table[bond, c1, c2] = find_cz(bond, c1, c2, z, krontable)
  69. return cz_table
  70. if __name__ == '__main__':
  71. unitaries = get_unitaries(DECOMPOSITIONS)
  72. conjugation_table = get_conjugation_table(unitaries)
  73. times_table = get_times_table(unitaries)
  74. cz_table = get_cz_table(unitaries)
  75. np.save("tables/unitaries.npy", unitaries)
  76. np.save("tables/conjugation_table.npy", conjugation_table)
  77. np.save("tables/times_table.npy", times_table)
  78. np.save("cz_table.npy", cz_table)