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.

113 lignes
3.3KB

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