168 lines
5.0 KiB
Python
168 lines
5.0 KiB
Python
import numpy as np
|
|
from benchmarks.libraries import abstract
|
|
|
|
|
|
class Cirq(abstract.ParserBackend):
|
|
|
|
def __init__(self):
|
|
import cirq
|
|
self.name = "cirq"
|
|
self.__version__ = cirq.__version__
|
|
self.cirq = cirq
|
|
self.precision = "double"
|
|
self.simulator = cirq.Simulator(dtype=np.complex128)
|
|
|
|
def RX(self, theta):
|
|
return self.cirq.rx(theta)
|
|
|
|
def RY(self, theta):
|
|
return self.cirq.ry(theta)
|
|
|
|
def RZ(self, theta):
|
|
return self.cirq.rz(theta)
|
|
|
|
def CU1(self, theta):
|
|
return self.cirq.CZPowGate(exponent=theta / np.pi)
|
|
|
|
def CU3(self, theta, phi, lam):
|
|
gate = self.cirq.circuits.qasm_output.QasmUGate(theta / np.pi, phi / np.pi, lam / np.pi)
|
|
return gate.controlled(num_controls=1)
|
|
|
|
def RZZ(self, theta):
|
|
import numpy as np
|
|
return self.cirq.ZZPowGate(exponent=theta / np.pi, global_shift=-0.5)
|
|
|
|
def __getattr__(self, x):
|
|
return getattr(self.cirq, x)
|
|
|
|
def __getitem__(self, x):
|
|
return getattr(self.cirq, x)
|
|
|
|
def from_qasm(self, qasm):
|
|
from cirq.contrib.qasm_import import circuit_from_qasm, exception
|
|
try:
|
|
return circuit_from_qasm(qasm)
|
|
except exception.QasmException:
|
|
nqubits, gatelist = self.parse(qasm)
|
|
qubits = [self.cirq.GridQubit(i, 0) for i in range(nqubits)]
|
|
circuit = self.cirq.Circuit()
|
|
for gatename, qid, params in gatelist:
|
|
if params is not None:
|
|
gate = getattr(self, gatename)(*params)
|
|
else:
|
|
gate = getattr(self, gatename)
|
|
circuit.append(gate(*(qubits[i] for i in qid)))
|
|
return circuit
|
|
|
|
def __call__(self, circuit):
|
|
result = self.simulator.simulate(circuit)
|
|
return result.final_state_vector
|
|
|
|
def transpose_state(self, x):
|
|
return x
|
|
|
|
def get_precision(self):
|
|
return self.precision
|
|
|
|
def set_precision(self, precision):
|
|
import numpy as np
|
|
self.precision = precision
|
|
if precision == "single":
|
|
self.simulator = self.cirq.Simulator(dtype=np.complex64)
|
|
else:
|
|
self.simulator = self.cirq.Simulator(dtype=np.complex128)
|
|
|
|
def get_device(self):
|
|
return None
|
|
|
|
|
|
class TensorflowQuantum(Cirq):
|
|
|
|
def __init__(self):
|
|
import cirq
|
|
import tensorflow_quantum as tfq
|
|
self.name = "tfq"
|
|
self.cirq = cirq
|
|
self.precision = "single"
|
|
self.__version__ = tfq.__version__
|
|
self.state_layer = tfq.layers.State()
|
|
|
|
def set_precision(self, precision):
|
|
if precision == "double":
|
|
raise NotImplementedError(f"Cannot set precision '{precision}' for {self.name} backend.")
|
|
|
|
def from_qasm(self, qasm):
|
|
circuit = super().from_qasm(qasm)
|
|
# change `NamedQubit`s to `GridQubit`s as TFQ understands only `GridQubit`
|
|
qubit_map = {}
|
|
for q in circuit.all_qubits():
|
|
if isinstance(q, self.cirq.NamedQubit):
|
|
i = int(str(q).split("_")[-1])
|
|
qubit_map[q] = self.cirq.GridQubit(i, 0)
|
|
if qubit_map:
|
|
return circuit.transform_qubits(qubit_map)
|
|
return circuit
|
|
|
|
def __call__(self, circuit):
|
|
# transfer final state to numpy array because that's what happens
|
|
# for all backends
|
|
return self.state_layer(circuit)[0].numpy()
|
|
|
|
|
|
class QSim(Cirq):
|
|
|
|
def __init__(self, max_qubits="0", nthreads=None):
|
|
import cirq
|
|
import qsimcirq
|
|
self.name = "qsim"
|
|
self.cirq = cirq
|
|
self.qsimcirq = qsimcirq
|
|
self.precision = "single"
|
|
self.__version__ = qsimcirq.__version__
|
|
|
|
if nthreads is None:
|
|
from multiprocessing import cpu_count
|
|
self.nthreads = cpu_count()
|
|
else:
|
|
self.nthreads = int(nthreads)
|
|
self.max_qubits = int(max_qubits)
|
|
|
|
self.simulator = self.get_simulator()
|
|
|
|
def get_simulator(self):
|
|
return self.qsimcirq.QSimSimulator({'t': self.nthreads, 'f': self.max_qubits})
|
|
|
|
def set_precision(self, precision):
|
|
if precision == "double":
|
|
raise NotImplementedError(f"Cannot set precision '{precision}' for {self.name} backend.")
|
|
|
|
|
|
class QSimGpu(QSim):
|
|
|
|
def __init__(self, max_qubits="0"):
|
|
super().__init__(max_qubits)
|
|
self.name = "qsim-gpu"
|
|
|
|
def get_simulator(self):
|
|
qsim_options = self.qsimcirq.QSimOptions(
|
|
use_gpu=True,
|
|
gpu_mode=0,
|
|
max_fused_gate_size=self.max_qubits
|
|
)
|
|
return self.qsimcirq.QSimSimulator(qsim_options)
|
|
|
|
|
|
class QSimCuQuantum(QSim):
|
|
|
|
def __init__(self, max_qubits="0"):
|
|
super().__init__(max_qubits)
|
|
self.name = "qsim-cuquantum"
|
|
|
|
def get_simulator(self):
|
|
qsim_options = self.qsimcirq.QSimOptions(
|
|
use_gpu=True,
|
|
gpu_mode=1,
|
|
max_fused_gate_size=self.max_qubits
|
|
)
|
|
return self.qsimcirq.QSimSimulator(qsim_options)
|