Skip to content

Commit 44cda51

Browse files
Fix explicitly calibrated gates in GateDirection (#9786) (#9788)
If there is an explicit calibration given, this overrides the generic information from the `CouplingMap` or the `Target` for that particular instance, since one can use pulse-level control to define gates on a circuit-by-circuit basis that are not generically available in a way that can be specified in the coupling or target. Co-authored-by: Jake Lishman <[email protected]>
1 parent 881e0d9 commit 44cda51

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

qiskit/transpiler/passes/utils/gate_direction.py

+4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ def _run_coupling_map(self, dag, wire_map, edges=None):
155155
continue
156156
if len(node.qargs) != 2:
157157
continue
158+
if dag.has_calibration_for(node):
159+
continue
158160
qargs = (wire_map[node.qargs[0]], wire_map[node.qargs[1]])
159161
if qargs not in edges and (qargs[1], qargs[0]) not in edges:
160162
raise TranspilerError(
@@ -198,6 +200,8 @@ def _run_target(self, dag, wire_map):
198200
continue
199201
if len(node.qargs) != 2:
200202
continue
203+
if dag.has_calibration_for(node):
204+
continue
201205
qargs = (wire_map[node.qargs[0]], wire_map[node.qargs[1]])
202206
swapped = (qargs[1], qargs[0])
203207
if node.name in self._static_replacements:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
The :class:`.GateDirection` transpiler pass will no longer reject gates that have been given
5+
explicit calibrations, but do not exist in the generic coupling map or target.

test/python/transpiler/test_gate_direction.py

+29-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717

1818
import ddt
1919

20-
from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit
21-
from qiskit.circuit import Parameter
20+
from qiskit import ClassicalRegister, QuantumRegister, QuantumCircuit, pulse
21+
from qiskit.circuit import Parameter, Gate
2222
from qiskit.circuit.library import CXGate, CZGate, ECRGate, RXXGate, RYYGate, RZXGate, RZZGate
2323
from qiskit.compiler import transpile
2424
from qiskit.transpiler import TranspilerError, CouplingMap, Target
@@ -430,6 +430,33 @@ def test_target_control_flow(self):
430430
pass_ = GateDirection(None, target)
431431
self.assertEqual(pass_(circuit), expected)
432432

433+
def test_allows_calibrated_gates_coupling_map(self):
434+
"""Test that the gate direction pass allows a gate that's got a calibration to pass through
435+
without error."""
436+
cm = CouplingMap([(1, 0)])
437+
438+
gate = Gate("my_2q_gate", 2, [])
439+
circuit = QuantumCircuit(2)
440+
circuit.append(gate, (0, 1))
441+
circuit.add_calibration(gate, (0, 1), pulse.ScheduleBlock())
442+
443+
pass_ = GateDirection(cm)
444+
self.assertEqual(pass_(circuit), circuit)
445+
446+
def test_allows_calibrated_gates_target(self):
447+
"""Test that the gate direction pass allows a gate that's got a calibration to pass through
448+
without error."""
449+
target = Target(num_qubits=2)
450+
target.add_instruction(CXGate(), properties={(0, 1): None})
451+
452+
gate = Gate("my_2q_gate", 2, [])
453+
circuit = QuantumCircuit(2)
454+
circuit.append(gate, (0, 1))
455+
circuit.add_calibration(gate, (0, 1), pulse.ScheduleBlock())
456+
457+
pass_ = GateDirection(None, target)
458+
self.assertEqual(pass_(circuit), circuit)
459+
433460

434461
if __name__ == "__main__":
435462
unittest.main()

0 commit comments

Comments
 (0)