state.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """
  2. Quantum Register Object
  3. """
  4. from qcgpu.backend import Backend
  5. import pyopencl as cl
  6. import numpy as np
  7. class State:
  8. """A class for representing quantum registers.
  9. The State class is the QCGPU representation of a quantum
  10. register / state vector.
  11. This class is what should be used to perform the simulations,
  12. and has method for things such as applying gates, measurements,
  13. getting probabilities and such.
  14. As QCGPU uses OpenCL, you may be queried about which OpenCL device
  15. to use. This will only happen when running things such a python repl,
  16. or running a script using QCGPU from the command line. Otherwise, a
  17. device will be chosen heuristically.
  18. When the register is created, it will be left in the state
  19. .. math::
  20. \\lvert 000 \\dots 0 \\rangle
  21. With the given number of qubits.
  22. Args:
  23. num_qubits (int): The number of qubits to create in the register.
  24. This must be greater then zero.
  25. Returns:
  26. State: A representation of the quantum register.
  27. Examples
  28. >>> qcgpu.State(3)
  29. Choose platform:
  30. [0] <pyopencl.Platform 'NVIDIA CUDA' at 0x2f22390>
  31. Choice [0]:0
  32. Set the environment variable PYOPENCL_CTX='0' to avoid being asked again.
  33. [[array(1.+0.j, dtype=complex64)]
  34. [array(0.+0.j, dtype=complex64)]
  35. [array(0.+0.j, dtype=complex64)]
  36. [array(0.+0.j, dtype=complex64)]]
  37. """
  38. def __init__(self, num_qubits):
  39. if not isinstance(num_qubits, int):
  40. raise ValueError("num_qubits must be an int")
  41. if num_qubits <= 0:
  42. raise ValueError("num_qubits must be a positive integer")
  43. #: The number of qubits that are in the register
  44. self.num_qubits = num_qubits
  45. self.backend = Backend(num_qubits)
  46. def apply_gate(self, gate, target):
  47. """Applies a single qubit unitary gate to the register.
  48. Args:
  49. gate (~qcgpu.Gate): The gate to be applied to the register
  50. target (int): The index of the qubit in the register that the gate
  51. is to be applied to.
  52. """
  53. if not isinstance(target, int) or target < 0:
  54. raise ValueError("target must be an int > 0")
  55. # TODO: Check that gate is correct
  56. self.backend.apply_gate(gate, target)
  57. def apply_all(self, gate):
  58. # TODO: Check that gate is correct
  59. for i in range(self.num_qubits):
  60. self.apply_gate(gate, i)
  61. def apply_controlled_gate(self, gate, control, target):
  62. if not isinstance(target, int) or target < 0:
  63. raise ValueError("target must be an int > 0")
  64. if not isinstance(control, int) or control < 0:
  65. raise ValueError("control must be an int > 0")
  66. # TODO: Check that gate is correct
  67. self.backend.apply_controlled_gate(gate, control, target)
  68. def measure_qubit(self, target, samples=1):
  69. return self.backend.measure_qubit(target, samples)
  70. def measure(self, samples=1):
  71. return self.backend.measure(samples)
  72. def amplitudes(self):
  73. return self.backend.amplitudes()
  74. def probabilities(self):
  75. return self.backend.probabilities()
  76. def flush(self):
  77. self.backend.release()
  78. def __repr__(self):
  79. """A string representation of the state"""
  80. # TODO: Finish this method
  81. return np.array_str(self.backend.buffer)