Make `qasm3.CustomGate` accessible from Python space (#13187)

We previously exposed the data attribute `STDGATES_INC_GATES`, but its
contents are all `CustomGate`, which can't be inspected programmatically
from Python space.  This makes it so you can query _what_ the gates,
their number of parameters, and how to construct them.
This commit is contained in:
Jake Lishman 2024-09-19 14:38:07 +01:00 committed by GitHub
parent 5121a0fda8
commit ece25b6b5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 3 deletions

View File

@ -65,12 +65,23 @@ register_type!(PyClassicalRegister);
/// Information received from Python space about how to construct a Python-space object to
/// represent a given gate that might be declared.
#[pyclass(module = "qiskit._accelerate.qasm3", frozen, name = "CustomGate")]
#[pyclass(
module = "qiskit._accelerate.qasm3",
frozen,
name = "CustomGate",
get_all
)]
#[derive(Clone, Debug)]
pub struct PyGate {
/// A callable Python object that takes ``num_params`` angles as positional arguments, and
/// returns a :class:`~.circuit.Gate` object representing the gate.
constructor: Py<PyAny>,
/// The name of the gate as it appears in the OpenQASM 3 program. This is not necessarily
/// identical to the name that Qiskit gives the gate.
name: String,
/// The number of angle-like parameters the gate requires.
num_params: usize,
/// The number of qubits the gate acts on.
num_qubits: usize,
}

View File

@ -50,7 +50,7 @@ use crate::error::QASM3ImporterError;
/// :class:`.QuantumCircuit`: the constructed circuit object.
///
/// Raises:
/// :class:`.QASM3ImporterError`: if an error occurred during parsing or semantic analysis.
/// :exc:`.QASM3ImporterError`: if an error occurred during parsing or semantic analysis.
/// In the case of a parsing error, most of the error messages are printed to the terminal
/// and formatted, for better legibility.
#[pyfunction]
@ -120,7 +120,7 @@ pub fn loads(
/// :class:`.QuantumCircuit`: the constructed circuit object.
///
/// Raises:
/// :class:`.QASM3ImporterError`: if an error occurred during parsing or semantic analysis.
/// :exc:`.QASM3ImporterError`: if an error occurred during parsing or semantic analysis.
/// In the case of a parsing error, most of the error messages are printed to the terminal
/// and formatted, for better legibility.
#[pyfunction]

View File

@ -209,6 +209,7 @@ custom Python constructors to use for particular gates. These custom constructo
using the :class:`CustomGate` object:
.. autoclass:: CustomGate
:members:
In ``custom_gates`` is not given, Qiskit will attempt to use its standard-library gate objects for
the gates defined in OpenQASM 3 standard library file ``stdgates.inc``. This sequence of gates is

View File

@ -0,0 +1,8 @@
---
features_qasm:
- |
The class :class:`.qasm3.CustomGate` is now inspectable programmatically. Its
:attr:`~.qasm3.CustomGate.constructor`, :attr:`~.qasm3.CustomGate.name`,
:attr:`~.qasm3.CustomGate.num_params` and :attr:`~.qasm3.CustomGate.num_qubits` can now be
viewed from Python after the object has been constructed. This allows you to inspect the
contents of provided data attributes like :data:`.STDGATES_INC_GATES`.

View File

@ -351,3 +351,17 @@ class TestQASM3Import(QiskitTestCase):
expected.ccx(q0[1], q1, q2[0])
expected.ccx(q0[0], q1, q2[1])
self.assertEqual(parsed, expected)
def test_custom_gate_inspectable(self):
"""Test that the `CustomGate` object can be inspected programmatically after creation."""
custom = qasm3.CustomGate(lib.CXGate, "cx", 0, 2)
self.assertEqual(custom.name, "cx")
self.assertEqual(custom.num_params, 0)
self.assertEqual(custom.num_qubits, 2)
self.assertIsInstance(qasm3.STDGATES_INC_GATES[0], qasm3.CustomGate)
stdgates = {
gate.name: (gate.num_params, gate.num_qubits) for gate in qasm3.STDGATES_INC_GATES
}
self.assertEqual(stdgates["rx"], (1, 1))
self.assertEqual(stdgates["cphase"], (1, 2))