86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
import numpy as np
|
|
from benchmarks.libraries import abstract
|
|
|
|
|
|
class QCGPU(abstract.ParserBackend):
|
|
|
|
def __init__(self):
|
|
import os
|
|
os.environ["PYOPENCL_CTX"] = "0"
|
|
import qcgpu
|
|
self.name = "qcgpu"
|
|
self.qcgpu = qcgpu
|
|
self.__version__ = None
|
|
|
|
def RX(self, target, theta):
|
|
cost, sint = np.cos(theta / 2.0), np.sin(theta / 2.0)
|
|
matrix = np.array([[cost, -1j * sint], [-1j * sint, cost]])
|
|
gate = self.qcgpu.Gate(matrix)
|
|
return ("apply_gate", (gate, target))
|
|
|
|
def RY(self, target, theta):
|
|
cost, sint = np.cos(theta / 2.0), np.sin(theta / 2.0)
|
|
matrix = np.array([[cost, -sint], [sint, cost]])
|
|
gate = self.qcgpu.Gate(matrix)
|
|
return ("apply_gate", (gate, target))
|
|
|
|
def RZ(self, target, theta):
|
|
phase = np.exp(0.5j * theta)
|
|
matrix = np.diag([np.conj(phase), phase])
|
|
gate = self.qcgpu.Gate(matrix)
|
|
return ("apply_gate", (gate, target))
|
|
|
|
def U1(self, target, theta):
|
|
phase = np.exp(1j * theta)
|
|
matrix = np.diag([1, phase])
|
|
gate = self.qcgpu.Gate(matrix)
|
|
return ("apply_gate", (gate, target))
|
|
|
|
def CU1(self, control, target, theta):
|
|
phase = np.exp(1j * theta)
|
|
matrix = np.diag([1, phase])
|
|
gate = self.qcgpu.Gate(matrix)
|
|
return ("apply_controlled_gate", (gate, control, target))
|
|
|
|
def RZZ(self, target1, target2, theta):
|
|
raise NotImplementedError
|
|
|
|
class QCGPUCircuit(list):
|
|
|
|
def __init__(self, nqubits):
|
|
self.nqubits = nqubits
|
|
|
|
def from_qasm(self, qasm):
|
|
nqubits, gatelist = self.parse(qasm)
|
|
circuit = self.QCGPUCircuit(nqubits)
|
|
for gate, qubits, params in gatelist:
|
|
args = list(qubits)
|
|
if params is not None:
|
|
args.extend(params)
|
|
if gate == "SWAP":
|
|
target1, target2 = qubits
|
|
circuit.append(("cx", (target1, target2)))
|
|
circuit.append(("cx", (target2, target1)))
|
|
circuit.append(("cx", (target1, target2)))
|
|
elif gate in {"RX", "RY", "RZ", "U1", "CU1"}:
|
|
circuit.append(getattr(self, gate)(*args))
|
|
else:
|
|
circuit.append((gate.lower(), args))
|
|
return circuit
|
|
|
|
def __call__(self, circuit):
|
|
state = self.qcgpu.State(circuit.nqubits)
|
|
for gate, args in circuit:
|
|
getattr(state, gate)(*args)
|
|
return state.amplitudes()
|
|
|
|
def set_precision(self, precision):
|
|
if precision != "single":
|
|
raise NotImplementedError(f"Cannot set {precision} precision for {self.name} backend.")
|
|
|
|
def get_precision(self):
|
|
return "single"
|
|
|
|
def get_device(self):
|
|
return None
|