diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index ccf9ff724abb..ac5079cb3e11 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -441,21 +441,26 @@ def calibrations(self, calibrations: dict): """ self._calibrations = defaultdict(dict, calibrations) - def has_calibration_for(self, instruction: CircuitInstruction): + def has_calibration_for(self, instruction: CircuitInstruction | tuple): """Return True if the circuit has a calibration defined for the instruction context. In this case, the operation does not need to be translated to the device basis. """ - if not self.calibrations or instruction.operation.name not in self.calibrations: + if isinstance(instruction, CircuitInstruction): + operation = instruction.operation + qubits = instruction.qubits + else: + operation, qubits, _ = instruction + if not self.calibrations or operation.name not in self.calibrations: return False - qubits = tuple(self.qubits.index(qubit) for qubit in instruction.qubits) + qubits = tuple(self.qubits.index(qubit) for qubit in qubits) params = [] - for p in instruction.operation.params: + for p in operation.params: if isinstance(p, ParameterExpression) and not p.parameters: params.append(float(p)) else: params.append(p) params = tuple(params) - return (qubits, params) in self.calibrations[instruction.operation.name] + return (qubits, params) in self.calibrations[operation.name] @property def metadata(self) -> dict: diff --git a/test/python/circuit/test_circuit_properties.py b/test/python/circuit/test_circuit_properties.py index 67c6cca5518b..806b771ea469 100644 --- a/test/python/circuit/test_circuit_properties.py +++ b/test/python/circuit/test_circuit_properties.py @@ -1255,6 +1255,43 @@ def test_calibrations_no_params(self): self.assertEqual(set(circ.calibrations["h"].keys()), {((0,), ())}) self.assertEqual(circ.calibrations["h"][((0,), ())].instructions, q0_x180.instructions) + def test_has_calibration_for(self): + """Test that `has_calibration_for` returns a correct answer.""" + qc = QuantumCircuit(3) + + with pulse.build() as q0_x180: + pulse.play(pulse.library.Gaussian(20, 1.0, 3.0), pulse.DriveChannel(0)) + qc.add_calibration("h", [0], q0_x180) + + qc.h(0) + qc.h(1) + + self.assertTrue(qc.has_calibration_for(qc.data[0])) + self.assertFalse(qc.has_calibration_for(qc.data[1])) + + def test_has_calibration_for_legacy(self): + """Test that `has_calibration_for` returns a correct answer when presented with a legacy 3 + tuple.""" + qc = QuantumCircuit(3) + + with pulse.build() as q0_x180: + pulse.play(pulse.library.Gaussian(20, 1.0, 3.0), pulse.DriveChannel(0)) + qc.add_calibration("h", [0], q0_x180) + + qc.h(0) + qc.h(1) + + self.assertTrue( + qc.has_calibration_for( + (qc.data[0].operation, list(qc.data[0].qubits), list(qc.data[0].clbits)) + ) + ) + self.assertFalse( + qc.has_calibration_for( + (qc.data[1].operation, list(qc.data[1].qubits), list(qc.data[1].clbits)) + ) + ) + def test_metadata_copy_does_not_share_state(self): """Verify mutating the metadata of a circuit copy does not impact original.""" # ref: https://github.com/Qiskit/qiskit-terra/issues/6057