Files
2026-05-19 17:19:36 +08:00

130 lines
4.3 KiB
Python

import numpy as np
from benchmarks.libraries import abstract
class ProjectQ(abstract.ParserBackend):
def __init__(self, max_qubits="0", local_optimizer="0"):
"""Initialize data members.
Args:
max_qubits (str): if "0", gate fusion is disabled, otherwise it's enabled.
Note that it's not possible to set the maximum fused gate size.
local_optimizer (str): if "0", local optimization of circuits is disabled,
otherwise it's enabled.
"""
import projectq
self.name = "projectq"
self.projectq = projectq
self.__version__ = None
self.gate_fusion = int(max_qubits) > 0
self.local_optimizer = bool(int(local_optimizer))
def RX(self, theta):
return self.projectq.ops.Rx(theta)
def RY(self, theta):
return self.projectq.ops.Ry(theta)
def RZ(self, theta):
return self.projectq.ops.Rz(theta)
def U1(self, theta):
return self.projectq.ops.R(theta)
def U2(self, phi, lam):
pplus, pminus = np.exp(0.5j * (phi + lam)), np.exp(0.5j * (phi - lam))
matrix = np.array([[np.conj(pplus), -np.conj(pminus)],
[pminus, pplus]])
matrix /= np.sqrt(2)
return self.projectq.ops.MatrixGate(matrix)
def U3(self, theta, phi, lam):
cost, sint = np.cos(theta / 2.0), np.sin(theta / 2.0)
pplus, pminus = np.exp(0.5j * (phi + lam)), np.exp(0.5j * (phi - lam))
matrix = np.array([[np.conj(pplus) * cost, -np.conj(pminus) * sint],
[pminus * sint, pplus * cost]])
return self.projectq.ops.MatrixGate(matrix)
def SWAP(self):
return self.projectq.ops.Swap
def CRX(self, theta):
return self.projectq.ops.C(self.RX(theta))
def CRY(self, theta):
return self.projectq.ops.C(self.RY(theta))
def CRZ(self, theta):
return self.projectq.ops.CRz(theta)
def CU1(self, theta):
U1 = self.projectq.ops.R(theta)
return self.projectq.ops.C(U1, n_qubits=1)
def CU3(self, theta):
raise NotImplementedError
def RZZ(self, theta):
return self.projectq.ops.Rzz(theta)
def __getattr__(self, x):
return getattr(self.projectq.ops, x)
def __item__(self, x):
return getattr(self.projectq.ops, x)
def from_qasm(self, qasm):
nqubits, gatelist = self.parse(qasm)
backend = self.projectq.backends.Simulator(gate_fusion=self.gate_fusion)
if self.local_optimizer:
self.eng = self.projectq.MainEngine(
backend=backend, engine_list=[self.projectq.cengines.LocalOptimizer()]
)
else:
self.eng = self.projectq.MainEngine(backend=backend)
qureg = self.eng.allocate_qureg(nqubits)
for gatename, qubits, params in gatelist:
gate = getattr(self, gatename)
if params is not None:
parameters = list(params)
if len(qubits) > 1:
gate(*parameters) | tuple(qureg[i] for i in qubits)
else:
gate(*parameters) | qureg[qubits[0]]
elif len(qubits) > 1:
if gatename == "SWAP":
gate() | tuple(qureg[i] for i in qubits)
else:
gate | tuple(qureg[i] for i in qubits)
else:
gate | qureg[qubits[0]]
return qureg
def __call__(self, qureg):
self.eng.flush()
self.qubit_id, wave = self.eng.backend.cheat()
# measure everything to avoid error when running
self.projectq.ops.All(self.projectq.ops.Measure) | qureg
return np.array(wave)
def transpose_state(self, x):
shape = tuple(x.shape)
nqubits = int(np.log2(shape[0]))
x = np.reshape(x, nqubits * (2,))
x = np.transpose(x, range(nqubits - 1, -1, -1))
x = np.transpose(x, tuple(self.qubit_id[key] for key in self.qubit_id))
x = np.reshape(x, shape)
return x
def set_precision(self, precision):
if precision != "double":
raise NotImplementedError(f"Cannot set {precision} precision for {self.name} backend.")
def get_precision(self):
return "double"
def get_device(self):
return None