final first commit
This commit is contained in:
173
qibojit-benchmarks/benchmarks/libraries/abstract.py
Normal file
173
qibojit-benchmarks/benchmarks/libraries/abstract.py
Normal file
@@ -0,0 +1,173 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import numpy as np
|
||||
|
||||
|
||||
class AbstractBackend(ABC):
|
||||
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.__version__ = None
|
||||
|
||||
@abstractmethod
|
||||
def from_qasm(self, qasm):
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def __call__(self, circuit):
|
||||
raise NotImplementedError
|
||||
|
||||
def transpose_state(self, x):
|
||||
"""Switch order of qubits in state vector to be compatible to Qibo."""
|
||||
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))
|
||||
return np.reshape(x, shape)
|
||||
|
||||
@abstractmethod
|
||||
def get_precision(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_precision(self, precision):
|
||||
raise NotImplementedError(f"Cannot set precision for {self.name} backend.")
|
||||
|
||||
@abstractmethod
|
||||
def get_device(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class ParserBackend(AbstractBackend):
|
||||
|
||||
QASM_GATES = {"h": "H", "x": "X", "y": "Y", "z": "Z",
|
||||
"rx": "RX", "ry": "RY", "rz": "RZ",
|
||||
"u1": "U1", "u2": "U2", "u3": "U3",
|
||||
"cx": "CNOT", "swap": "SWAP", "cz": "CZ",
|
||||
"crx": "CRX", "cry": "CRY", "crz": "CRZ",
|
||||
"cu1": "CU1", "cu3": "CU3", "rzz": "RZZ",
|
||||
"ccx": "TOFFOLI", "id": "I"}
|
||||
PARAMETRIZED_GATES = {"rx", "ry", "rz", "u1", "u2", "u3",
|
||||
"crx", "cry", "crz", "cu1", "cu3", "rzz"}
|
||||
|
||||
def parse(self, qasm_code):
|
||||
"""Extracts circuit information from QASM script.
|
||||
|
||||
Args:
|
||||
qasm_code: String with the QASM code to parse.
|
||||
|
||||
Returns:
|
||||
nqubits: The total number of qubits in the circuit.
|
||||
gate_list: List that specifies the gates of the circuit.
|
||||
Contains tuples of the form
|
||||
(Qibo gate name, qubit IDs, optional additional parameter).
|
||||
The additional parameter is the ``register_name`` for
|
||||
measurement gates or ``theta`` for parametrized gates.
|
||||
"""
|
||||
import re
|
||||
def read_args(args):
|
||||
_args = iter(re.split(r"[\[\],]", args))
|
||||
for name in _args:
|
||||
if name:
|
||||
index = next(_args)
|
||||
if not index.isdigit():
|
||||
raise ValueError("Invalid QASM qubit arguments: {}".format(args))
|
||||
yield name, int(index)
|
||||
|
||||
# Remove comment lines
|
||||
lines = "".join(line for line in qasm_code.split("\n")
|
||||
if line and line[:2] != "//")
|
||||
lines = (line for line in lines.split(";") if line)
|
||||
|
||||
if next(lines) != "OPENQASM 2.0":
|
||||
raise ValueError("QASM code should start with 'OPENQASM 2.0'.")
|
||||
|
||||
qubits = {} # Dict[Tuple[str, int], int]: map from qubit tuple to qubit id
|
||||
cregs_size = {} # Dict[str, int]: map from `creg` name to its size
|
||||
registers = {} # Dict[str, List[int]]: map from register names to target qubit ids
|
||||
gate_list = [] # List[Tuple[str, List[int]]]: List of (gate name, list of target qubit ids)
|
||||
for line in lines:
|
||||
command, args = line.split(None, 1)
|
||||
# remove spaces
|
||||
command = command.replace(" ", "")
|
||||
args = args.replace(" ", "")
|
||||
|
||||
if command == "include":
|
||||
pass
|
||||
|
||||
elif command == "qreg":
|
||||
for name, nqubits in read_args(args):
|
||||
for i in range(nqubits):
|
||||
qubits[(name, i)] = len(qubits)
|
||||
|
||||
elif command == "creg":
|
||||
for name, nqubits in read_args(args):
|
||||
cregs_size[name] = nqubits
|
||||
|
||||
elif command == "measure":
|
||||
args = args.split("->")
|
||||
if len(args) != 2:
|
||||
raise ValueError("Invalid QASM measurement: {}".format(line))
|
||||
qubit = next(read_args(args[0]))
|
||||
if qubit not in qubits:
|
||||
raise ValueError("Qubit {} is not defined in QASM code."
|
||||
"".format(qubit))
|
||||
|
||||
register, idx = next(read_args(args[1]))
|
||||
if register not in cregs_size:
|
||||
raise ValueError("Classical register name {} is not defined "
|
||||
"in QASM code.".format(register))
|
||||
if idx >= cregs_size[register]:
|
||||
raise ValueError("Cannot access index {} of register {} "
|
||||
"with {} qubits."
|
||||
"".format(idx, register, cregs_size[register]))
|
||||
if register in registers:
|
||||
if idx in registers[register]:
|
||||
raise KeyError("Key {} of register {} has already "
|
||||
"been used.".format(idx, register))
|
||||
registers[register][idx] = qubits[qubit]
|
||||
else:
|
||||
registers[register] = {idx: qubits[qubit]}
|
||||
gate_list.append(("M", register))
|
||||
|
||||
else:
|
||||
pieces = [x for x in re.split("[()]", command) if x]
|
||||
if len(pieces) == 1:
|
||||
gatename, params = pieces[0], None
|
||||
if gatename not in self.QASM_GATES:
|
||||
raise ValueError("QASM command {} is not recognized."
|
||||
"".format(command))
|
||||
if gatename in self.PARAMETRIZED_GATES:
|
||||
raise ValueError("Missing parameters for QASM "
|
||||
"gate {}.".format(gatename))
|
||||
|
||||
elif len(pieces) == 2:
|
||||
gatename, params = pieces
|
||||
if gatename not in self.PARAMETRIZED_GATES:
|
||||
raise ValueError("Invalid QASM command {}."
|
||||
"".format(command))
|
||||
params = params.replace(" ", "").split(",")
|
||||
try:
|
||||
for i, p in enumerate(params):
|
||||
if 'pi' in p:
|
||||
import math
|
||||
from operator import mul
|
||||
from functools import reduce
|
||||
s = p.replace('pi', str(math.pi)).split('*')
|
||||
p = reduce(mul, [float(j) for j in s], 1)
|
||||
params[i] = float(p)
|
||||
except ValueError:
|
||||
raise ValueError("Invalid value {} for gate parameters."
|
||||
"".format(params))
|
||||
|
||||
else:
|
||||
raise ValueError("QASM command {} is not recognized."
|
||||
"".format(command))
|
||||
|
||||
# Add gate to gate list
|
||||
qubit_list = []
|
||||
for qubit in read_args(args):
|
||||
if qubit not in qubits:
|
||||
raise ValueError("Qubit {} is not defined in QASM "
|
||||
"code.".format(qubit))
|
||||
qubit_list.append(qubits[qubit])
|
||||
gate_list.append((self.QASM_GATES[gatename], list(qubit_list), params))
|
||||
return len(qubits), gate_list
|
||||
Reference in New Issue
Block a user