Skip to content

Commit

Permalink
Fix arguments for RZXCalibrationBuilder and EchoRZXWeylDecomposition
Browse files Browse the repository at this point in the history
The RZXCalibrationBuilder and EchoRZXWeylDecomposition transpiler passes
were previously taking BaseBackend instances as arguments. Besides that
being a deprecated class which will be removed soon, it also is
incorrect because backend objects are not guaranteed to be pickleable so
when a pass manager runs in parallel processes this will cause an error.
This was never caught because these passes aren't part of any default
pass managers and their tests don't include running them as part of
transpile().

To fix this passes typically take the properties of a backend they
require. This is being reworked for BackendV2 in #5885 so a target
object can be used to encapsulate the model of a backend so we have a
single data structure to pass around, but until that is the minimum
backend version we need to also support taking the individual components
for BackendV1 and BaseBackend.

This commit changes the pass constructors to take only use the parameters
from the backend object used in the pass internals and stop requiring a
backend object be used to construct an instance of either pass.
  • Loading branch information
mtreinish committed Dec 1, 2021
1 parent b807eb4 commit 4bb889f
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 23 deletions.
24 changes: 13 additions & 11 deletions qiskit/transpiler/passes/calibration/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from qiskit.circuit.library.standard_gates import RZXGate
from qiskit.dagcircuit import DAGCircuit
from qiskit.exceptions import QiskitError
from qiskit.providers import basebackend
from qiskit.pulse import (
Play,
Delay,
Expand Down Expand Up @@ -103,26 +102,29 @@ class RZXCalibrationBuilder(CalibrationBuilder):
angle. Additional details can be found in https://arxiv.org/abs/2012.11660.
"""

def __init__(self, backend: basebackend):
def __init__(
self,
instruction_schedule_map: InstructionScheduleMap,
qubit_channel_mapping: List[List[str]],
):
"""
Initializes a RZXGate calibration builder.
Args:
backend: Backend for which to construct the gates.
instruction_schedule_map: The :obj:`InstructionScheduleMap` object representing the
default pulse calibrations for the target backend
qubit_channel_mapping: The list mapping qubit indices to the list of
channel names that apply on that qubit.
Raises:
QiskitError: if open pulse is not supported by the backend.
"""
super().__init__()
if not backend.configuration().open_pulse:
raise QiskitError(
"Calibrations can only be added to Pulse-enabled backends, "
"but {} is not enabled with Pulse.".format(backend.name())
)
if instruction_schedule_map is None or qubit_channel_mapping is None:
raise QiskitError("Calibrations can only be added to Pulse-enabled backends")

self._inst_map = backend.defaults().instruction_schedule_map
self._config = backend.configuration()
self._channel_map = backend.configuration().qubit_channel_mapping
self._inst_map = instruction_schedule_map
self._channel_map = qubit_channel_mapping

def supported(self, node_op: CircuitInst, qubits: List) -> bool:
"""Determine if a given node supports the calibration.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
from qiskit.dagcircuit import DAGCircuit
from qiskit.converters import circuit_to_dag

from qiskit.providers import basebackend

import qiskit.quantum_info as qi
from qiskit.quantum_info.synthesis.two_qubit_decompose import TwoQubitControlledUDecomposer

Expand All @@ -38,10 +36,10 @@ class EchoRZXWeylDecomposition(TransformationPass):
Each pair of RZXGates forms an echoed RZXGate.
"""

def __init__(self, backend: basebackend):
def __init__(self, instruction_schedule_map: "InstructionScheduleMap"):
"""EchoRZXWeylDecomposition pass."""
self._inst_map = backend.defaults().instruction_schedule_map
super().__init__()
self._inst_map = instruction_schedule_map

def _is_native(self, qubit_pair: Tuple) -> bool:
"""Return the direction of the qubit pair that is native, i.e. with the shortest schedule."""
Expand Down
5 changes: 4 additions & 1 deletion test/python/pulse/test_calibrationbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ def test_rzx_calibration_builder(self):
self.assertEqual(rzx_qc.calibrations, {})

# apply the RZXCalibrationBuilderNoEcho.
pass_ = RZXCalibrationBuilderNoEcho(self.backend)
pass_ = RZXCalibrationBuilderNoEcho(
self.backend.defaults().instruction_schedule_map,
self.backend.configuration().qubit_channel_mapping,
)
cal_qc = PassManager(pass_).run(rzx_qc)
rzx_qc_duration = schedule(cal_qc, self.backend).duration

Expand Down
15 changes: 8 additions & 7 deletions test/python/transpiler/test_echo_rzx_weyl_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class TestEchoRZXWeylDecomposition(QiskitTestCase):
def setUp(self):
super().setUp()
self.backend = FakeParis()
self.inst_map = self.backend.defaults().instruction_schedule_map

def assertRZXgates(self, unitary_circuit, after):
"""Check the number of rzx gates"""
Expand Down Expand Up @@ -74,7 +75,7 @@ def test_rzx_number_native_weyl_decomposition(self):

unitary_circuit = qi.Operator(circuit).data

after = EchoRZXWeylDecomposition(self.backend)(circuit)
after = EchoRZXWeylDecomposition(self.inst_map)(circuit)

unitary_after = qi.Operator(after).data

Expand All @@ -96,11 +97,11 @@ def test_h_number_non_native_weyl_decomposition_1(self):
circuit_non_native.rzz(theta, qr[1], qr[0])

dag = circuit_to_dag(circuit)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after = dag_to_circuit(pass_.run(dag))

dag_non_native = circuit_to_dag(circuit_non_native)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after_non_native = dag_to_circuit(pass_.run(dag_non_native))

circuit_rzx_number = self.count_gate_number("rzx", after)
Expand All @@ -126,11 +127,11 @@ def test_h_number_non_native_weyl_decomposition_2(self):
circuit_non_native.swap(qr[1], qr[0])

dag = circuit_to_dag(circuit)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after = dag_to_circuit(pass_.run(dag))

dag_non_native = circuit_to_dag(circuit_non_native)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after_non_native = dag_to_circuit(pass_.run(dag_non_native))

circuit_rzx_number = self.count_gate_number("rzx", after)
Expand Down Expand Up @@ -165,7 +166,7 @@ def test_weyl_decomposition_gate_angles(self):
unitary_circuit = qi.Operator(circuit).data

dag = circuit_to_dag(circuit)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after = dag_to_circuit(pass_.run(dag))
dag_after = circuit_to_dag(after)

Expand Down Expand Up @@ -220,7 +221,7 @@ def test_weyl_unitaries_random_circuit(self):
unitary_circuit = qi.Operator(circuit).data

dag = circuit_to_dag(circuit)
pass_ = EchoRZXWeylDecomposition(self.backend)
pass_ = EchoRZXWeylDecomposition(self.inst_map)
after = dag_to_circuit(pass_.run(dag))

unitary_after = qi.Operator(after).data
Expand Down

0 comments on commit 4bb889f

Please sign in to comment.