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.

150 lignes
4.8KB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Exposes a few basic QI operators
  5. And a circuit-model simulator
  6. """
  7. from __future__ import absolute_import
  8. import numpy as np
  9. import itertools as it
  10. from fractions import Fraction
  11. from six.moves import range
  12. from six.moves import zip
  13. def hermitian_conjugate(u):
  14. """ Shortcut to the Hermitian conjugate """
  15. return np.conjugate(np.transpose(u))
  16. # Constants
  17. ir2 = 1 / np.sqrt(2)
  18. # Operators
  19. id = np.array(np.eye(2, dtype=complex))
  20. px = np.array([[0, 1], [1, 0]], dtype=complex)
  21. py = np.array([[0, -1j], [1j, 0]], dtype=complex)
  22. pz = np.array([[1, 0], [0, -1]], dtype=complex)
  23. ha = hadamard = np.array([[1, 1], [1, -1]], dtype=complex) * ir2
  24. ph = np.array([[1, 0], [0, 1j]], dtype=complex)
  25. t = np.array([[1, 0], [0, np.exp(1j * np.pi / 4)]], dtype=complex)
  26. sqx = np.array(
  27. [[1. + 0.j, -0. + 1.j], [-0. + 1.j, 1. - 0.j]], dtype=complex) * ir2
  28. msqx = np.array(
  29. [[1. + 0.j, 0. - 1.j], [0. - 1.j, 1. - 0.j]], dtype=complex) * ir2
  30. sqy = np.array(
  31. [[1. + 0.j, 1. + 0.j], [-1. - 0.j, 1. - 0.j]], dtype=complex) * ir2
  32. msqy = np.array(
  33. [[1. + 0.j, -1. - 0.j], [1. + 0.j, 1. - 0.j]], dtype=complex) * ir2
  34. sqz = np.array(
  35. [[1. + 1.j, 0. + 0.j], [0. + 0.j, 1. - 1.j]], dtype=complex) * ir2
  36. msqz = np.array(
  37. [[1. - 1.j, 0. + 0.j], [0. + 0.j, 1. + 1.j]], dtype=complex) * ir2
  38. # CZ gate
  39. cz = np.array(np.eye(4), dtype=complex)
  40. cz[3, 3] = -1
  41. # States
  42. zero = np.array([[1], [0]], dtype=complex)
  43. one = np.array([[0], [1]], dtype=complex)
  44. plus = np.array([[1], [1]], dtype=complex) / np.sqrt(2)
  45. bond = cz.dot(np.kron(plus, plus))
  46. nobond = np.kron(plus, plus)
  47. # Labelling stuff
  48. common_us = id, px, py, pz, ha, ph, sqz, msqz, sqy, msqy, sqx, msqx
  49. names = "identity", "px", "py", "pz", "hadamard", "phase", "sqz", "msqz", "sqy", "msqy", "sqx", "msqx"
  50. by_name = dict(list(zip(names, common_us)))
  51. paulis = px, py, pz
  52. operators = id, px, py, pz
  53. def normalize_global_phase(m):
  54. """ Normalize the global phase of a matrix """
  55. v = next((x for x in m.flatten() if np.abs(x) > 0.001))
  56. phase = np.arctan2(v.imag, v.real) % np.pi
  57. rot = np.exp(-1j * phase)
  58. return rot * m if rot * v > 0 else -rot * m
  59. class CircuitModel(object):
  60. def __init__(self, nqubits):
  61. self.nqubits = nqubits
  62. self.d = 2 ** nqubits
  63. self.state = np.zeros((self.d, 1), dtype=complex)
  64. self.state[0, 0] = 1
  65. def act_cz(self, control, target):
  66. """ Act a CU somewhere. """
  67. control = 1 << control
  68. target = 1 << target
  69. for i in range(self.d):
  70. if (i & control) and (i & target):
  71. self.state[i, 0] *= -1
  72. def act_cnot(self, control, target):
  73. """ Act a CNOT. """
  74. self.act_hadamard(target)
  75. self.act_cz(control, target)
  76. self.act_hadamard(target)
  77. def act_hadamard(self, qubit):
  78. """ Act a hadamard somewhere. """
  79. where = 1 << qubit
  80. output = np.zeros((self.d, 1), dtype=complex)
  81. for i, v in enumerate(self.state):
  82. q = int(i & where > 0)
  83. output[i] += v * ha[q, q]
  84. output[i ^ where] += v * ha[int(not q), q]
  85. self.state = output
  86. def act_local_rotation(self, qubit, u):
  87. """ Act a local unitary somwhere. """
  88. where = 1 << qubit
  89. output = np.zeros((self.d, 1), dtype=complex)
  90. for i, v in enumerate(self.state):
  91. q = int(i & where > 0)
  92. output[i] += v * u[q, q]
  93. output[i ^ where] += v * u[int(not q), q]
  94. self.state = output
  95. def act_circuit(self, circuit):
  96. """ Act a sequence of gates. """
  97. for node, operation in circuit:
  98. if operation == "cz":
  99. self.act_cz(*node)
  100. else:
  101. self.act_local_rotation(node, operation)
  102. def __eq__(self, other):
  103. """ Check whether two quantum states are the same or not,
  104. up to a global phase. """
  105. a = normalize_global_phase(self.state)
  106. b = normalize_global_phase(other.state)
  107. return np.allclose(a, b)
  108. def __setitem__(self, key, value):
  109. """ Set a matrix element """
  110. self.state[key] = value
  111. def __getitem__(self, key):
  112. """ Get a matrix element """
  113. return self.state[key]
  114. def __str__(self):
  115. s = ""
  116. for i in range(self.d):
  117. label = bin(i)[2:].rjust(self.nqubits, "0")[::-1]
  118. if abs(self.state[i, 0]) > 0.00001:
  119. term = self.state[i, 0]
  120. real_sign = " " if term.real>=0 else "-"
  121. real_frac = Fraction(str(term.real**2)).limit_denominator()
  122. imag_sign = "+" if term.imag>=0 else "-"
  123. imag_frac = Fraction(str(term.imag**2)).limit_denominator()
  124. s += "|{}❭: \t{}√{}\t{} i √{}\n".format(
  125. label, real_sign, real_frac, imag_sign, imag_frac)
  126. return s