Anders and Briegel in Python
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

114 lignes
3.6KB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Exposes a few basic QI operators
  5. And a circuit-model simulator
  6. """
  7. import numpy as np
  8. import itertools as it
  9. def hermitian_conjugate(u):
  10. """ Shortcut to the Hermitian conjugate """
  11. return np.conjugate(np.transpose(u))
  12. # Constants
  13. ir2 = 1/np.sqrt(2)
  14. # Operators
  15. id = np.array(np.eye(2, dtype=complex))
  16. px = np.array([[0, 1], [1, 0]], dtype=complex)
  17. py = np.array([[0, -1j], [1j, 0]], dtype=complex)
  18. pz = np.array([[1, 0], [0, -1]], dtype=complex)
  19. ha = hadamard = np.array([[1, 1], [1, -1]], dtype=complex) * ir2
  20. ph = np.array([[1, 0], [0, 1j]], dtype=complex)
  21. t = np.array([[1, 0], [0, np.exp(1j*np.pi/4)]], dtype=complex)
  22. sqx = np.array([[ 1.+0.j, -0.+1.j], [-0.+1.j, 1.-0.j]], dtype=complex)*ir2
  23. msqx = np.array([[ 1.+0.j, 0.-1.j], [ 0.-1.j, 1.-0.j]], dtype=complex)*ir2
  24. sqy = np.array([[ 1.+0.j, 1.+0.j], [-1.-0.j, 1.-0.j]], dtype=complex)*ir2
  25. msqy = np.array([[ 1.+0.j, -1.-0.j], [ 1.+0.j, 1.-0.j]], dtype=complex)*ir2
  26. sqz = np.array([[ 1.+1.j, 0.+0.j], [ 0.+0.j, 1.-1.j]], dtype=complex)*ir2
  27. msqz = np.array([[ 1.-1.j, 0.+0.j], [ 0.+0.j, 1.+1.j]], dtype=complex)*ir2
  28. # CZ gate
  29. cz = np.array(np.eye(4), dtype=complex)
  30. cz[3,3]=-1
  31. # States
  32. zero = np.array([[1],[0]], dtype=complex)
  33. one = np.array([[0],[1]], dtype=complex)
  34. plus = np.array([[1],[1]], dtype=complex) / np.sqrt(2)
  35. bond = cz.dot(np.kron(plus, plus))
  36. nobond = np.kron(plus, plus)
  37. # Labelling stuff
  38. common_us = id, px, py, pz, ha, ph, sqz, msqz, sqy, msqy, sqx, msqx
  39. names = "identity", "px", "py", "pz", "hadamard", "phase", "sqz", "msqz", "sqy", "msqy", "sqx", "msqx"
  40. by_name = dict(zip(names, common_us))
  41. paulis = px, py, pz
  42. operators = id, px, py, pz
  43. def normalize_global_phase(m):
  44. """ Normalize the global phase of a matrix """
  45. v = (x for x in m.flatten() if np.abs(x) > 0.001).next()
  46. phase = np.arctan2(v.imag, v.real) % np.pi
  47. rot = np.exp(-1j * phase)
  48. return rot * m if rot * v > 0 else -rot * m
  49. class CircuitModel(object):
  50. def __init__(self, nqubits):
  51. self.nqubits = nqubits
  52. self.d = 2**nqubits
  53. self.state = np.zeros((self.d, 1), dtype=complex)
  54. self.state[0, 0]=1
  55. def act_cz(self, control, target):
  56. """ Act a CU somewhere """
  57. control = 1 << control
  58. target = 1 << target
  59. for i in xrange(self.d):
  60. if (i & control) and (i & target):
  61. self.state[i, 0] *= -1
  62. def act_hadamard(self, qubit):
  63. """ Act a hadamard somewhere """
  64. where = 1 << qubit
  65. output = np.zeros((self.d, 1), dtype=complex)
  66. for i, v in enumerate(self.state):
  67. q = i & where > 0
  68. output[i] += v*ha[q, q]
  69. output[i ^ where] += v*ha[not q, q]
  70. self.state = output
  71. def act_local_rotation(self, qubit, u):
  72. """ Act a local unitary somwhere """
  73. where = 1 << qubit
  74. output = np.zeros((self.d, 1), dtype=complex)
  75. for i, v in enumerate(self.state):
  76. q = i & where > 0
  77. output[i] += v*u[q, q] # TODO this is probably wrong
  78. output[i ^ where] += v*u[not q, q]
  79. self.state = output
  80. def __eq__(self, other):
  81. """ Check whether two quantum states are the same or not
  82. UP TO A GLOBAL PHASE """
  83. a = normalize_global_phase(self.state)
  84. b = normalize_global_phase(other.state)
  85. return np.allclose(a, b)
  86. def __str__(self):
  87. s = ""
  88. for i in range(self.d):
  89. label = bin(i)[2:].rjust(self.nqubits, "0")
  90. if abs(self.state[i, 0])>0.00001:
  91. s += "|{}>: {}\n".format(label, self.state[i, 0].round(3))
  92. return s