final first commit
This commit is contained in:
53
qibojit-benchmarks/benchmarks/circuits/__init__.py
Normal file
53
qibojit-benchmarks/benchmarks/circuits/__init__.py
Normal file
@@ -0,0 +1,53 @@
|
||||
def parse(options):
|
||||
"""Parse options from string.
|
||||
|
||||
Args:
|
||||
options (str): String with options.
|
||||
It should have the form 'arg1=value1,arg2=value2,...'.
|
||||
|
||||
Returns:
|
||||
dict: {'arg1': value1, 'arg2': value2, ...}
|
||||
|
||||
"""
|
||||
kwargs = {}
|
||||
if options is not None:
|
||||
for parameter in options.split(","):
|
||||
if "=" in parameter:
|
||||
k, v = parameter.split("=")
|
||||
kwargs[k] = v
|
||||
else:
|
||||
raise ValueError(f"Cannot parse parameter {parameter}.")
|
||||
return kwargs
|
||||
|
||||
|
||||
def get(circuit_name, nqubits, options=None, qibo=False):
|
||||
if qibo:
|
||||
from benchmarks.circuits import qibo as module
|
||||
else:
|
||||
from benchmarks.circuits import qasm as module
|
||||
|
||||
if circuit_name in ("qft", "QFT"):
|
||||
circuit = module.QFT
|
||||
elif circuit_name == "one-qubit-gate":
|
||||
circuit = module.OneQubitGate
|
||||
elif circuit_name == "two-qubit-gate":
|
||||
circuit = module.TwoQubitGate
|
||||
elif circuit_name in ("variational", "variational-circuit"):
|
||||
circuit = module.VariationalCircuit
|
||||
elif circuit_name in ("bernstein-vazirani", "bv"):
|
||||
circuit = module.BernsteinVazirani
|
||||
elif circuit_name in ("hidden-shift", "hs"):
|
||||
circuit = module.HiddenShift
|
||||
elif circuit_name == "qaoa":
|
||||
circuit = module.QAOA
|
||||
elif circuit_name == "supremacy":
|
||||
circuit = module.SupremacyCircuit
|
||||
elif circuit_name in ("basis-change", "bc"):
|
||||
circuit = module.BasisChange
|
||||
elif circuit_name in ("quantum-volume", "qv"):
|
||||
circuit = module.QuantumVolume
|
||||
else:
|
||||
raise NotImplementedError(f"Cannot find circuit {circuit_name}.")
|
||||
|
||||
kwargs = parse(options)
|
||||
return circuit(nqubits, **kwargs)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
394
qibojit-benchmarks/benchmarks/circuits/qasm.py
Normal file
394
qibojit-benchmarks/benchmarks/circuits/qasm.py
Normal file
@@ -0,0 +1,394 @@
|
||||
import numpy as np
|
||||
from abc import abstractmethod
|
||||
|
||||
|
||||
class AbstractCircuit:
|
||||
|
||||
def __init__(self, nqubits):
|
||||
self.nqubits = nqubits
|
||||
self.parameters = {}
|
||||
|
||||
@abstractmethod
|
||||
def __iter__(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def to_qasm(self, theta=None):
|
||||
"""Creates the circuit in OpenQASM format.
|
||||
|
||||
Args:
|
||||
theta (np.ndarray): If not ``None`` ``RX`` gates with the given
|
||||
angles are added before the actual circuit gates so that the
|
||||
initial state is non-trivial. Useful for testing.
|
||||
|
||||
Returns:
|
||||
A string with the circuit in OpenQASM format.
|
||||
"""
|
||||
code = ['OPENQASM 2.0;', 'include "qelib1.inc";',
|
||||
f'qreg q[{self.nqubits}];', f'creg m[{self.nqubits}];']
|
||||
if theta is not None:
|
||||
code.extend(f"rx({t}) q[{i}];" for i, t in enumerate(theta))
|
||||
code.extend(iter(self))
|
||||
return "\n".join(code)
|
||||
|
||||
def __str__(self):
|
||||
return ", ".join(f"{k}={v}" for k, v in self.parameters.items())
|
||||
|
||||
|
||||
class OneQubitGate(AbstractCircuit):
|
||||
"""Applies a specific one qubit gate to all qubits."""
|
||||
|
||||
def __init__(self, nqubits, nlayers="1", gate="h", angles=""):
|
||||
super().__init__(nqubits)
|
||||
self.gate = gate
|
||||
self.nlayers = int(nlayers)
|
||||
self.angles = angles
|
||||
self.parameters = {"nqubits": nqubits, "nlayers": nlayers,
|
||||
"gate": gate, "params": angles}
|
||||
|
||||
def base_command(self, i):
|
||||
if self.angles:
|
||||
return "{}({}) q[{}];".format(self.gate, self.angles, i)
|
||||
else:
|
||||
return "{} q[{}];".format(self.gate, i)
|
||||
|
||||
def __iter__(self):
|
||||
for _ in range(self.nlayers):
|
||||
for i in range(self.nqubits):
|
||||
yield self.base_command(i)
|
||||
|
||||
|
||||
class TwoQubitGate(OneQubitGate):
|
||||
"""Applies a specific two qubit gate to all pairs of adjacent qubits."""
|
||||
|
||||
def __init__(self, nqubits, nlayers="1", gate="cx", angles=""):
|
||||
super().__init__(nqubits, nlayers, gate, angles)
|
||||
|
||||
def base_command(self, i):
|
||||
if self.angles:
|
||||
return "{}({}) q[{}],q[{}];".format(self.gate, self.angles, i, i + 1)
|
||||
else:
|
||||
return "{} q[{}],q[{}];".format(self.gate, i, i + 1)
|
||||
|
||||
def __iter__(self):
|
||||
for _ in range(self.nlayers):
|
||||
for i in range(0, self.nqubits - 1, 2):
|
||||
yield self.base_command(i)
|
||||
for i in range(1, self.nqubits - 1, 2):
|
||||
yield self.base_command(i)
|
||||
|
||||
|
||||
class QFT(AbstractCircuit):
|
||||
"""Applies the Quantum Fourier Transform."""
|
||||
|
||||
def __init__(self, nqubits, swaps="True"):
|
||||
super().__init__(nqubits)
|
||||
self.swaps = swaps == "True"
|
||||
self.parameters = {"nqubits": nqubits, "swaps": swaps}
|
||||
|
||||
def __iter__(self):
|
||||
for i1 in range(self.nqubits):
|
||||
yield f"h q[{i1}];"
|
||||
for i2 in range(i1 + 1, self.nqubits):
|
||||
theta = np.pi / 2 ** (i2 - i1)
|
||||
yield f"cu1({theta}) q[{i2}],q[{i1}];"
|
||||
|
||||
if self.swaps:
|
||||
for i in range(self.nqubits // 2):
|
||||
yield f"swap q[{i}],q[{self.nqubits - i - 1}];"
|
||||
|
||||
|
||||
class VariationalCircuit(AbstractCircuit):
|
||||
"""Example variational circuit consisting of alternating layers of RY and CZ gates."""
|
||||
|
||||
def __init__(self, nqubits, nlayers="1", seed="123"):
|
||||
super().__init__(nqubits)
|
||||
self.nlayers = int(nlayers)
|
||||
self.seed = int(seed)
|
||||
self.parameters = {"nqubits": nqubits, "nlayers": nlayers, "seed": seed}
|
||||
|
||||
def __iter__(self):
|
||||
nparams = 2 * self.nlayers * self.nqubits
|
||||
np.random.seed(self.seed)
|
||||
theta = iter(2 * np.pi * np.random.random(nparams))
|
||||
for l in range(self.nlayers):
|
||||
for i in range(self.nqubits):
|
||||
yield f"ry({next(theta)}) q[{i}];"
|
||||
for i in range(0, self.nqubits - 1, 2):
|
||||
yield f"cz q[{i}],q[{i + 1}];"
|
||||
for i in range(self.nqubits):
|
||||
yield f"ry({next(theta)}) q[{i}];"
|
||||
for i in range(1, self.nqubits - 2, 2):
|
||||
yield f"cz q[{i}],q[{i + 1}];"
|
||||
yield f"cz q[{0}],q[{self.nqubits - 1}];"
|
||||
|
||||
|
||||
class BernsteinVazirani(AbstractCircuit):
|
||||
"""Applies the Bernstein-Vazirani algorithm from Qiskit/openqasm.
|
||||
|
||||
See `https://github.com/Qiskit/openqasm/tree/0af8b8489f32d46692b3a3a1421e98c611cd86cc/benchmarks/bv`
|
||||
for the OpenQASM code.
|
||||
Note that `Barrier` gates are excluded for simulation.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits):
|
||||
super().__init__(nqubits)
|
||||
self.parameters = {"nqubits": nqubits}
|
||||
|
||||
def __iter__(self):
|
||||
yield f"x q[{self.nqubits - 1}];"
|
||||
for i in range(self.nqubits):
|
||||
yield f"h q[{i}];"
|
||||
for i in range(self.nqubits - 1):
|
||||
yield f"cx q[{i}],q[{self.nqubits - 1}];"
|
||||
for i in range(self.nqubits - 1):
|
||||
yield f"h q[{i}];"
|
||||
#for i in range(self.nqubits - 1):
|
||||
# yield f"measure m[{i}];"
|
||||
|
||||
|
||||
class HiddenShift(AbstractCircuit):
|
||||
"""Applies the Hidden Shift algorithm.
|
||||
|
||||
See `https://github.com/quantumlib/Cirq/blob/master/examples/hidden_shift_algorithm.py`
|
||||
for the Cirq code.
|
||||
If the shift (hidden bitstring) is not given then it is randomly generated
|
||||
using `np.random.randint`.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits, shift=""):
|
||||
super().__init__(nqubits)
|
||||
if len(shift):
|
||||
if len(shift) != nqubits:
|
||||
raise ValueError("Shift bitstring of length {} was given for "
|
||||
"circuit of {} qubits."
|
||||
"".format(len(shift), nqubits))
|
||||
self.shift = [int(x) for x in shift]
|
||||
else:
|
||||
self.shift = np.random.randint(0, 2, size=(self.nqubits,))
|
||||
self.parameters = {"nqubits": nqubits, "shift": shift}
|
||||
|
||||
def oracle(self):
|
||||
for i in range(self.nqubits // 2):
|
||||
yield f"cz q[{2 * i}],q[{2 * i + 1}];"
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(self.nqubits):
|
||||
yield f"h q[{i}];"
|
||||
for i, ish in enumerate(self.shift):
|
||||
if ish:
|
||||
yield f"x q[{i}];"
|
||||
for gate in self.oracle():
|
||||
yield gate
|
||||
for i, ish in enumerate(self.shift):
|
||||
if ish:
|
||||
yield f"x q[{i}];"
|
||||
for i in range(self.nqubits):
|
||||
yield f"h q[{i}];"
|
||||
for gate in self.oracle():
|
||||
yield gate
|
||||
for i in range(self.nqubits):
|
||||
yield f"h q[{i}];"
|
||||
#for i in range(self.nqubits):
|
||||
# yield f"measure m[{i}];"
|
||||
|
||||
|
||||
class QAOA(AbstractCircuit):
|
||||
"""Example QAOA circuit for a MaxCut problem instance.
|
||||
|
||||
See `https://github.com/quantumlib/Cirq/blob/master/examples/qaoa.py` for
|
||||
the Cirq code.
|
||||
If a JSON file containing the node link structure is given then the graph
|
||||
is loaded using `networkx.readwrite.json_graph.node_link_graph`, otherwise
|
||||
the graph is generated randomly using `networkx.random_regular_graph`.
|
||||
Note that different graphs may lead to different performance as the graph
|
||||
structure affects circuit depth.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits, nparams="2", graph="", seed="123"):
|
||||
super().__init__(nqubits)
|
||||
import networkx
|
||||
self.nparams = int(nparams)
|
||||
self.seed = int(seed)
|
||||
if len(graph):
|
||||
import json
|
||||
with open(graph, "r") as file:
|
||||
data = json.load(file)
|
||||
self.graph = networkx.readwrite.json_graph.node_link_graph(data)
|
||||
else:
|
||||
self.graph = networkx.random_regular_graph(
|
||||
3, self.nqubits, seed=self.seed
|
||||
)
|
||||
self.parameters = {"nqubits": nqubits, "nparams": nparams,
|
||||
"graph": graph, "seed": seed}
|
||||
|
||||
@staticmethod
|
||||
def RX(q, theta):
|
||||
return f"rx({theta}) q[{q}];"
|
||||
|
||||
@staticmethod
|
||||
def RZZ(q0, q1, theta):
|
||||
return f"rzz({theta}) q[{q0}],q[{q1}];"
|
||||
|
||||
def maxcut_unitary(self, betas, gammas):
|
||||
for beta, gamma in zip(betas, gammas):
|
||||
for i, j in self.graph.edges:
|
||||
yield self.RZZ(i, j, -0.5 * gamma)
|
||||
for i in range(self.nqubits):
|
||||
yield self.RX(i, 2 * beta)
|
||||
|
||||
def dump(self, dir):
|
||||
"""Saves graph data as JSON in given directory."""
|
||||
import json
|
||||
import networkx
|
||||
data = networkx.readwrite.json_graph.node_link_data(self.graph)
|
||||
with open(dir, "w") as file:
|
||||
json.dump(data, file)
|
||||
|
||||
def __iter__(self):
|
||||
np.random.seed(self.seed)
|
||||
betas = np.random.uniform(-np.pi, np.pi, size=self.nparams)
|
||||
gammas = np.random.uniform(-np.pi, np.pi, size=self.nparams)
|
||||
# Prepare uniform superposition
|
||||
for i in range(self.nqubits):
|
||||
yield f"h q[{i}];"
|
||||
# Apply QAOA unitary
|
||||
for gate in self.maxcut_unitary(betas, gammas):
|
||||
yield gate
|
||||
# Measure
|
||||
# yield gates.M(*range(self.nqubits))
|
||||
|
||||
|
||||
class SupremacyCircuit(AbstractCircuit):
|
||||
"""Random circuit by Boixo et al 2018 for demonstrating quantum supremacy.
|
||||
|
||||
See `https://github.com/quantumlib/Cirq/blob/v0.11.0/cirq-core/cirq/experiments/google_v2_supremacy_circuit.py`
|
||||
for the Cirq code.
|
||||
This circuit is constructed using `cirq` by exporting to OpenQASM and
|
||||
importing back to Qibo.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits, depth="2", seed="123"):
|
||||
super().__init__(nqubits)
|
||||
self.depth = int(depth)
|
||||
self.seed = int(seed)
|
||||
self.parameters = {"nqubits": nqubits, "depth": depth, "seed": seed}
|
||||
self.cirq_circuit = self.create_cirq_circuit()
|
||||
|
||||
def create_cirq_circuit(self):
|
||||
import cirq
|
||||
from cirq.experiments import google_v2_supremacy_circuit as spc
|
||||
qubits = [cirq.GridQubit(i, 0) for i in range(self.nqubits)]
|
||||
return spc.generate_boixo_2018_supremacy_circuits_v2(qubits, self.depth, self.seed)
|
||||
|
||||
def __iter__(self):
|
||||
qasm = self.cirq_circuit.to_qasm()
|
||||
for line in qasm.split("\n"):
|
||||
first_word = line.split(" ")[0]
|
||||
if first_word not in {"//", "OPENQASM", "include", "qreg"}:
|
||||
if first_word == "sx":
|
||||
yield line.replace("sx", "rx(pi*0.5)") # see issue #13
|
||||
else:
|
||||
yield line
|
||||
|
||||
|
||||
class BasisChange(AbstractCircuit):
|
||||
"""Basis change fermionic circuit.
|
||||
|
||||
See `https://quantumai.google/openfermion/tutorials/circuits_1_basis_change`
|
||||
for OpenFermion/Cirq code.
|
||||
This circuit is constructed using `openfermion` and `cirq` by exporting
|
||||
to OpenQASM and importing back to Qibo.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits, simulation_time="1", seed="123"):
|
||||
super().__init__(nqubits)
|
||||
self.simulation_time = float(simulation_time)
|
||||
self.seed = int(seed)
|
||||
self.parameters = {"nqubits": nqubits, "simulation_time": simulation_time,
|
||||
"seed": seed}
|
||||
self.openfermion_circuit = self.create_openfermion_circuit()
|
||||
|
||||
def create_openfermion_circuit(self):
|
||||
import cirq
|
||||
import openfermion
|
||||
# Generate the random one-body operator.
|
||||
T = openfermion.random_hermitian_matrix(self.nqubits, seed=self.seed)
|
||||
# Diagonalize T and obtain basis transformation matrix (aka "u").
|
||||
eigenvalues, eigenvectors = np.linalg.eigh(T)
|
||||
basis_transformation_matrix = eigenvectors.transpose()
|
||||
# Initialize the qubit register.
|
||||
qubits = cirq.LineQubit.range(self.nqubits)
|
||||
# Start circuit with the inverse basis rotation, print out this step.
|
||||
inverse_basis_rotation = cirq.inverse(openfermion.bogoliubov_transform(qubits, basis_transformation_matrix))
|
||||
circuit = cirq.Circuit(inverse_basis_rotation)
|
||||
# Add diagonal phase rotations to circuit.
|
||||
for k, eigenvalue in enumerate(eigenvalues):
|
||||
phase = -eigenvalue * self.simulation_time
|
||||
circuit.append(cirq.rz(rads=phase).on(qubits[k]))
|
||||
# Finally, restore basis.
|
||||
basis_rotation = openfermion.bogoliubov_transform(qubits, basis_transformation_matrix)
|
||||
circuit.append(basis_rotation)
|
||||
return circuit
|
||||
|
||||
def __iter__(self):
|
||||
qasm = self.openfermion_circuit.to_qasm()
|
||||
for line in qasm.split("\n"):
|
||||
first_word = line.split(" ")[0]
|
||||
if first_word not in {"//", "OPENQASM", "include", "qreg"}:
|
||||
yield line
|
||||
|
||||
|
||||
class QuantumVolume(AbstractCircuit):
|
||||
"""Quantum Volume circuit from Qiskit.
|
||||
|
||||
See `https://qiskit.org/documentation/stubs/qiskit.circuit.library.QuantumVolume.html`
|
||||
for the Qiskit model.
|
||||
This circuit is constructed using `qiskit` by exporting to OpenQASM and
|
||||
importing back to Qibo.
|
||||
"""
|
||||
|
||||
def __init__(self, nqubits, depth="1", seed="123"):
|
||||
super().__init__(nqubits)
|
||||
self.depth = int(depth)
|
||||
self.seed = int(seed)
|
||||
self.parameters = {"nqubits": nqubits, "depth": depth, "seed": seed}
|
||||
self.qiskit_circuit = self.create_qiskit_circuit()
|
||||
self.expression_symbols = {"*", "/"}
|
||||
self.expression_symbols.update(str(x) for x in range(10))
|
||||
|
||||
def create_qiskit_circuit(self):
|
||||
from qiskit.circuit.library import QuantumVolume
|
||||
circuit = QuantumVolume(self.nqubits, self.depth, seed=self.seed)
|
||||
return circuit.decompose().decompose()
|
||||
|
||||
def __iter__(self):
|
||||
raise NotImplementedError("Iteration is not available for "
|
||||
"`QuantumVolume` because it is prepared "
|
||||
"using Qiskit.")
|
||||
|
||||
def evaluate_pi(self, qasm):
|
||||
left = qasm.find("pi")
|
||||
if left < 0:
|
||||
return qasm
|
||||
|
||||
import sympy
|
||||
right = left + 2
|
||||
left = left - 1
|
||||
while qasm[left] in self.expression_symbols:
|
||||
left -= 1
|
||||
while qasm[right] in self.expression_symbols:
|
||||
right += 1
|
||||
expr = qasm[left + 1: right]
|
||||
evaluated = sympy.sympify(expr).evalf()
|
||||
return self.evaluate_pi(qasm.replace(expr, str(evaluated)))
|
||||
|
||||
def __iter__(self):
|
||||
qasm = self.qiskit_circuit.qasm()
|
||||
for line in qasm.split("\n"):
|
||||
first_word = line.split(" ")[0]
|
||||
if first_word not in {"//", "OPENQASM", "include", "qreg"}:
|
||||
yield line.replace("1/(15*pi)", str(1.0 / (15.0 * np.pi)))
|
||||
|
||||
def to_qasm(self, theta=None):
|
||||
qasm = super().to_qasm(theta)
|
||||
return self.evaluate_pi(qasm)
|
||||
218
qibojit-benchmarks/benchmarks/circuits/qibo.py
Normal file
218
qibojit-benchmarks/benchmarks/circuits/qibo.py
Normal file
@@ -0,0 +1,218 @@
|
||||
import numpy as np
|
||||
from qibo import gates
|
||||
from benchmarks.circuits import qasm
|
||||
|
||||
|
||||
class OneQubitGate(qasm.OneQubitGate):
|
||||
|
||||
def __init__(self, nqubits, nlayers="1", gate="H", **params):
|
||||
super().__init__(nqubits, nlayers=nlayers, gate=gate)
|
||||
self.gate = getattr(gates, gate)
|
||||
self.angles = {k: float(v) for k, v in params.items()}
|
||||
self.parameters = {"nqubits": nqubits, "nlayers": nlayers,
|
||||
"gate": gate, "params": params}
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def base_command(self, i):
|
||||
return self.gate(i, **self.angles)
|
||||
|
||||
|
||||
class TwoQubitGate(OneQubitGate):
|
||||
|
||||
def __init__(self, nqubits, nlayers="1", gate="CNOT", **params):
|
||||
super().__init__(nqubits, nlayers, gate, **params)
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def base_command(self, i):
|
||||
return self.gate(i, i + 1, **self.angles)
|
||||
|
||||
def __iter__(self):
|
||||
return qasm.TwoQubitGate.__iter__(self)
|
||||
|
||||
|
||||
class QFT(qasm.QFT):
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __iter__(self):
|
||||
for i1 in range(self.nqubits):
|
||||
yield gates.H(i1)
|
||||
for i2 in range(i1 + 1, self.nqubits):
|
||||
theta = np.pi / 2 ** (i2 - i1)
|
||||
yield gates.CU1(i2, i1, theta)
|
||||
|
||||
if self.swaps:
|
||||
for i in range(self.nqubits // 2):
|
||||
yield gates.SWAP(i, self.nqubits - i - 1)
|
||||
|
||||
|
||||
class VariationalCircuit(qasm.VariationalCircuit):
|
||||
|
||||
def __init__(self, nqubits, nlayers=1, varlayer="False", seed="123"):
|
||||
super().__init__(nqubits, nlayers, seed)
|
||||
self.varlayer = varlayer == "True"
|
||||
self.parameters["varlayer"] = varlayer
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def varlayer_circuit(self, theta):
|
||||
theta = theta.reshape((2 * self.nlayers, self.nqubits))
|
||||
pairs = list((i, i + 1) for i in range(0, self.nqubits - 1, 2))
|
||||
for l in range(self.nlayers):
|
||||
yield gates.VariationalLayer(range(self.nqubits), pairs,
|
||||
gates.RY, gates.CZ,
|
||||
theta[2 * l], theta[2 * l + 1])
|
||||
for i in range(1, self.nqubits - 2, 2):
|
||||
yield gates.CZ(i, i + 1)
|
||||
yield gates.CZ(0, self.nqubits - 1)
|
||||
|
||||
def standard_circuit(self, theta):
|
||||
theta = iter(theta)
|
||||
for l in range(self.nlayers):
|
||||
for i in range(self.nqubits):
|
||||
yield gates.RY(i, next(theta))
|
||||
for i in range(0, self.nqubits - 1, 2):
|
||||
yield gates.CZ(i, i + 1)
|
||||
for i in range(self.nqubits):
|
||||
yield gates.RY(i, next(theta))
|
||||
for i in range(1, self.nqubits - 2, 2):
|
||||
yield gates.CZ(i, i + 1)
|
||||
yield gates.CZ(0, self.nqubits - 1)
|
||||
|
||||
def __iter__(self):
|
||||
np.random.seed(self.seed)
|
||||
theta = 2 * np.pi * np.random.random(2 * self.nlayers * self.nqubits)
|
||||
if self.varlayer:
|
||||
return self.varlayer_circuit(theta)
|
||||
else:
|
||||
return self.standard_circuit(theta)
|
||||
|
||||
|
||||
class BernsteinVazirani(qasm.BernsteinVazirani):
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __iter__(self):
|
||||
yield gates.X(self.nqubits - 1)
|
||||
for i in range(self.nqubits):
|
||||
yield gates.H(i)
|
||||
for i in range(self.nqubits - 1):
|
||||
yield gates.CNOT(i, self.nqubits - 1)
|
||||
for i in range(self.nqubits - 1):
|
||||
yield gates.H(i)
|
||||
for i in range(self.nqubits - 1):
|
||||
yield gates.M(i)
|
||||
|
||||
|
||||
class HiddenShift(qasm.HiddenShift):
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def oracle(self):
|
||||
for i in range(self.nqubits // 2):
|
||||
yield gates.CZ(2 * i, 2 * i + 1)
|
||||
|
||||
def __iter__(self):
|
||||
for i in range(self.nqubits):
|
||||
yield gates.H(i)
|
||||
for i, ish in enumerate(self.shift):
|
||||
if ish:
|
||||
yield gates.X(i)
|
||||
for gate in self.oracle():
|
||||
yield gate
|
||||
for i, ish in enumerate(self.shift):
|
||||
if ish:
|
||||
yield gates.X(i)
|
||||
for i in range(self.nqubits):
|
||||
yield gates.H(i)
|
||||
for gate in self.oracle():
|
||||
yield gate
|
||||
for i in range(self.nqubits):
|
||||
yield gates.H(i)
|
||||
yield gates.M(*range(self.nqubits))
|
||||
|
||||
|
||||
class QAOA(qasm.QAOA):
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def RX(q, theta):
|
||||
return gates.RX(q, theta=theta)
|
||||
|
||||
@staticmethod
|
||||
def RZZ(q0, q1, theta):
|
||||
phase = np.exp(0.5j * theta)
|
||||
phasec = np.conj(phase)
|
||||
matrix = np.diag([phasec, phase, phase, phasec])
|
||||
return gates.Unitary(matrix, q0, q1)
|
||||
|
||||
def __iter__(self):
|
||||
np.random.seed(self.seed)
|
||||
betas = np.random.uniform(-np.pi, np.pi, size=self.nparams)
|
||||
gammas = np.random.uniform(-np.pi, np.pi, size=self.nparams)
|
||||
# Prepare uniform superposition
|
||||
for i in range(self.nqubits):
|
||||
yield gates.H(i)
|
||||
# Apply QAOA unitary
|
||||
for gate in self.maxcut_unitary(betas, gammas):
|
||||
yield gate
|
||||
# Measure
|
||||
yield gates.M(*range(self.nqubits))
|
||||
|
||||
|
||||
class SupremacyCircuit(qasm.SupremacyCircuit):
|
||||
|
||||
def __init__(self, nqubits, depth="2", seed="123"):
|
||||
super().__init__(nqubits, depth, seed)
|
||||
from qibo import models
|
||||
parent = qasm.SupremacyCircuit(nqubits, depth, seed)
|
||||
self.qibo_circuit = models.Circuit.from_qasm(parent.to_qasm())
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __iter__(self):
|
||||
for gate in self.qibo_circuit.queue:
|
||||
yield gate
|
||||
|
||||
|
||||
class BasisChange(qasm.BasisChange):
|
||||
|
||||
def __init__(self, nqubits, simulation_time="1", seed="123"):
|
||||
super().__init__(nqubits, simulation_time, seed)
|
||||
from qibo import models
|
||||
parent = qasm.BasisChange(nqubits, simulation_time, seed)
|
||||
self.qibo_circuit = models.Circuit.from_qasm(parent.to_qasm())
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __iter__(self):
|
||||
for gate in self.qibo_circuit.queue:
|
||||
yield gate
|
||||
|
||||
|
||||
class QuantumVolume(qasm.QuantumVolume):
|
||||
|
||||
def __init__(self, nqubits, depth="1", seed="123"):
|
||||
super().__init__(nqubits, depth, seed)
|
||||
from qibo import models
|
||||
parent = qasm.QuantumVolume(nqubits, depth, seed)
|
||||
self.qibo_circuit = models.Circuit.from_qasm(parent.to_qasm())
|
||||
|
||||
def to_qasm(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __iter__(self):
|
||||
for gate in self.qibo_circuit.queue:
|
||||
yield gate
|
||||
Reference in New Issue
Block a user