Skip to content

Commit

Permalink
Add full path transpile() tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mtreinish committed Mar 21, 2023
1 parent f0a498e commit 5631d96
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 3 deletions.
6 changes: 4 additions & 2 deletions qiskit/transpiler/passes/layout/disjoint_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ def run_pass_over_connected_components(
dag = dag_components[dag_index]
out_dag.add_qubits(dag.qubits)
out_dag.add_clbits(dag.clbits)
out_dag.add_qreg(dag.qregs)
out_dag.add_cregs(dag.cregs)
for qreg in dag.qregs:
out_dag.add_qreg(qreg)
for creg in dag.cregs:
out_dag.add_cregs(creg)
out_dag.compose(dag, qubits=dag.qubits, clbits=dag.clbits)
out_component_pairs.append((out_dag, cmap_components[cmap_index]))
res = [run_func(out_dag, cmap) for out_dag, cmap in out_component_pairs]
Expand Down
194 changes: 193 additions & 1 deletion test/python/compiler/test_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from test import combine # pylint: disable=wrong-import-order

import numpy as np
import rustworkx as rx

from qiskit.exceptions import QiskitError
from qiskit import BasicAer
Expand All @@ -42,9 +43,12 @@
RZGate,
UGate,
CZGate,
XGate,
SXGate,
)
from qiskit.circuit import IfElseOp, WhileLoopOp, ForLoopOp, ControlFlowOp
from qiskit.circuit.measure import Measure
from qiskit.circuit.delay import Delay
from qiskit.test import QiskitTestCase
from qiskit.providers.fake_provider import (
FakeMelbourne,
Expand All @@ -55,14 +59,16 @@
)
from qiskit.transpiler import Layout, CouplingMap
from qiskit.transpiler import PassManager, TransformationPass
from qiskit.transpiler.target import Target
from qiskit.transpiler.target import Target, InstructionProperties
from qiskit.transpiler.exceptions import TranspilerError
from qiskit.transpiler.passes import BarrierBeforeFinalMeasurements, GateDirection
from qiskit.quantum_info import Operator, random_unitary
from qiskit.transpiler.passmanager_config import PassManagerConfig
from qiskit.transpiler.preset_passmanagers import level_0_pass_manager
from qiskit.tools import parallel
from qiskit.pulse import InstructionScheduleMap
from qiskit.providers.backend import BackendV2
from qiskit.providers.options import Options


class CustomCX(Gate):
Expand Down Expand Up @@ -1971,3 +1977,189 @@ def test_backend_and_custom_gate(self, opt_level):
self.assertEqual(tqc.data[0].operation, newgate)
qubits = tuple(tqc.find_bit(x).index for x in tqc.data[0].qubits)
self.assertIn(qubits, backend.target.qargs)


@ddt
class TestTranspileMultiChipTarget(QiskitTestCase):
"""Test transpile() with a disjoint coupling map."""

def setUp(self):
super().setUp()

class FakeMultiChip(BackendV2):
"""Fake multi chip backend."""

def __init__(self):
super().__init__()
graph = rx.generators.directed_heavy_hex_graph(3)
num_qubits = len(graph) * 3
rng = np.random.default_rng(seed=12345678942)
rz_props = {}
x_props = {}
sx_props = {}
measure_props = {}
delay_props = {}
self._target = Target("Fake multi-chip backend", num_qubits=num_qubits)
for i in range(num_qubits):
qarg = (i,)
rz_props[qarg] = InstructionProperties(error=0.0, duration=0.0)
x_props[qarg] = InstructionProperties(
error=rng.uniform(1e-6, 1e-4), duration=rng.uniform(1e-8, 9e-7)
)
sx_props[qarg] = InstructionProperties(
error=rng.uniform(1e-6, 1e-4), duration=rng.uniform(1e-8, 9e-7)
)
measure_props[qarg] = InstructionProperties(
error=rng.uniform(1e-3, 1e-1), duration=rng.uniform(1e-8, 9e-7)
)
delay_props[qarg] = None
self._target.add_instruction(XGate(), x_props)
self._target.add_instruction(SXGate(), sx_props)
self._target.add_instruction(RZGate(Parameter("theta")), rz_props)
self._target.add_instruction(Measure(), measure_props)
self._target.add_instruction(Delay(Parameter("t")), delay_props)
cz_props = {}
for i in range(3):
for root_edge in graph.edge_list():
offset = i * len(graph)
edge = (root_edge[0] + offset, root_edge[1] + offset)
cz_props[edge] = InstructionProperties(
error=rng.uniform(1e-5, 5e-3), duration=rng.uniform(1e-8, 9e-7)
)
self._target.add_instruction(CZGate(), cz_props)

@property
def target(self):
return self._target

@property
def max_circuits(self):
return None

@classmethod
def _default_options(cls):
return Options(shots=1024)

def run(self, circuit, **kwargs):
raise NotImplementedError

self.backend = FakeMultiChip()

# Add level 0 and 1 when TrivialLayout supports disjoint coupling maps
@data(2, 3)
def test_basic_connected_circuit(self, opt_level):
"""Test basic connected circuit on disjoint backend"""
qc = QuantumCircuit(5)
qc.h(0)
qc.cx(0, 1)
qc.cx(0, 2)
qc.cx(0, 3)
qc.cx(0, 4)
qc.measure_all()
tqc = transpile(qc, self.backend, optimization_level=opt_level)
for inst in tqc.data:
qubits = tuple(tqc.find_bit(x).index for x in inst.qubits)
op_name = inst.operation.name
if op_name == "barrier":
continue
self.assertIn(qubits, self.backend.target[op_name])

# Add level 0 and 1 when TrivialLayout supports disjoint coupling maps
@data(2, 3)
def test_triple_circuit(self, opt_level):
"""Test a split circuit with one circuit component per chip."""
qc = QuantumCircuit(30)
qc.h(0)
qc.h(10)
qc.h(20)
qc.cx(0, 1)
qc.cx(0, 2)
qc.cx(0, 3)
qc.cx(0, 4)
qc.cx(0, 5)
qc.cx(0, 6)
qc.cx(0, 7)
qc.cx(0, 8)
qc.cx(0, 9)
qc.ecr(10, 11)
qc.ecr(10, 12)
qc.ecr(10, 13)
qc.ecr(10, 14)
qc.ecr(10, 15)
qc.ecr(10, 16)
qc.ecr(10, 17)
qc.ecr(10, 18)
qc.ecr(10, 19)
qc.cy(20, 21)
qc.cy(20, 22)
qc.cy(20, 23)
qc.cy(20, 24)
qc.cy(20, 25)
qc.cy(20, 26)
qc.cy(20, 27)
qc.cy(20, 28)
qc.cy(20, 29)
qc.measure_all()
tqc = transpile(qc, self.backend, optimization_level=opt_level, seed_transpiler=42)
for inst in tqc.data:
qubits = tuple(tqc.find_bit(x).index for x in inst.qubits)
op_name = inst.operation.name
if op_name == "barrier":
continue
self.assertIn(qubits, self.backend.target[op_name])

# Add level 0 and 1 when TrivialLayout supports disjoint coupling maps
@data(2, 3)
def test_six_component_circuit(self, opt_level):
"""Test input circuit with more than 1 component per backend component."""
qc = QuantumCircuit(42)
qc.h(0)
qc.h(10)
qc.h(20)
qc.cx(0, 1)
qc.cx(0, 2)
qc.cx(0, 3)
qc.cx(0, 4)
qc.cx(0, 5)
qc.cx(0, 6)
qc.cx(0, 7)
qc.cx(0, 8)
qc.cx(0, 9)
qc.ecr(10, 11)
qc.ecr(10, 12)
qc.ecr(10, 13)
qc.ecr(10, 14)
qc.ecr(10, 15)
qc.ecr(10, 16)
qc.ecr(10, 17)
qc.ecr(10, 18)
qc.ecr(10, 19)
qc.cy(20, 21)
qc.cy(20, 22)
qc.cy(20, 23)
qc.cy(20, 24)
qc.cy(20, 25)
qc.cy(20, 26)
qc.cy(20, 27)
qc.cy(20, 28)
qc.cy(20, 29)
qc.h(30)
qc.cx(30, 31)
qc.cx(30, 32)
qc.cx(30, 33)
qc.h(34)
qc.cx(34, 35)
qc.cx(34, 36)
qc.cx(34, 37)
qc.h(38)
qc.cx(38, 39)
qc.cx(39, 40)
qc.cx(39, 41)
qc.measure_all()
tqc = transpile(qc, self.backend, optimization_level=opt_level, seed_transpiler=42)
for inst in tqc.data:
qubits = tuple(tqc.find_bit(x).index for x in inst.qubits)
op_name = inst.operation.name
if op_name == "barrier":
continue
self.assertIn(qubits, self.backend.target[op_name])

0 comments on commit 5631d96

Please sign in to comment.