From 8e520bb1adf67921b751638ce4276b4134578631 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Thu, 30 Mar 2023 13:01:07 -0400 Subject: [PATCH] Add public layout attribute to QuantumCircuit (#9486) * Add public layout attribute to QuantumCircuit Since the Qiskit 0.9.0 release the QuantumCircuit has had a private `_layout` attribute which is used to track the permutations introduced to a circuit by the transpiler. At the time this was made private because we didn't want to commit to an interface on this at the time until a dedicated API could be introduced (see #2853). However, since that time ~4 years ago we've never introduced an alternative public interface for `_layout` was never introduced. This has left users needing to reason about the permutation caused by transpile() in a weird place because the only mechanism to do this is private. This commit adds a public read-only attribute `.layout` to solve this, which just exposes the previously private `._layout` attribute via a documented and public interface. Unlike from 0.9.x through 0.21.x we introduced a new data class container `TranspileLayout` as part of the 0.22.0 release which _layout was updated to use at the time. Having a dedicated class used for the field gives us a certain degree of flexibility to evolve the interface over time if needed. Right now it contains 3 pieces of information the initial layout caused by the layout phase of transpile(), the input qubit mapping to figure out the qubit index on the original circuit, and the final layout caused by swaps inserted during routing. Closes #8803 * Fix typo in QuantumCircuit.layout docs * Disable cyclic import check on conditional type hint import --- qiskit/circuit/quantumcircuit.py | 18 +++++++++++ qiskit/transpiler/__init__.py | 3 +- qiskit/transpiler/layout.py | 30 ++++++++++++++++++- ...add-layout-attribute-c84e56c08ca93ada.yaml | 10 +++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/add-layout-attribute-c84e56c08ca93ada.yaml diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index 2d883758e3d3..71b214bf14ff 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -71,6 +71,7 @@ if typing.TYPE_CHECKING: import qiskit # pylint: disable=cyclic-import + from qiskit.transpiler.layout import TranspileLayout # pylint: disable=cyclic-import BitLocations = namedtuple("BitLocations", ("index", "registers")) @@ -355,6 +356,23 @@ def from_instructions( circuit._append(instruction) return circuit + @property + def layout(self) -> Optional[TranspileLayout]: + r"""Return any associated layout information anout the circuit + + This attribute contains an optional :class:`~.TranspileLayout` + object. This is typically set on the output from :func:`~.transpile` + or :meth:`.PassManager.run` to retain information about the + permutations caused on the input circuit by transpilation. + + There are two types of permutations caused by the :func:`~.transpile` + function, an initial layout which permutes the qubits based on the + selected physical qubits on the :class:`~.Target`, and a final layout + which is an output permutation caused by :class:`~.SwapGate`\s + inserted during routing. + """ + return self._layout + @property def data(self) -> QuantumCircuitData: """Return the circuit data (instructions and context). diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index f01a92cc853a..76cd6fc3d6f4 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -1210,6 +1210,7 @@ Layout CouplingMap + TranspileLayout Scheduling ---------- @@ -1256,7 +1257,7 @@ from .fencedobjs import FencedDAGCircuit, FencedPropertySet from .basepasses import AnalysisPass, TransformationPass from .coupling import CouplingMap -from .layout import Layout +from .layout import Layout, TranspileLayout from .instruction_durations import InstructionDurations from .target import Target from .target import InstructionProperties diff --git a/qiskit/transpiler/layout.py b/qiskit/transpiler/layout.py index eb29c6c80fd1..56f8f7f50954 100644 --- a/qiskit/transpiler/layout.py +++ b/qiskit/transpiler/layout.py @@ -370,7 +370,35 @@ def from_qubit_list(qubit_list, *qregs): @dataclass class TranspileLayout: - """Layout attributes from output circuit from transpiler.""" + r"""Layout attributes from output circuit from transpiler. + + The transpiler in general is unitary-perserving up to permutations caused + by setting and applying initial layout during the :ref:`layout_stage` + and :class:`~.SwapGate` insertion during the :ref:`routing_stage`. To + provide an interface to reason about these permutations caused by + the :mod:`~qiskit.transpiler`. + + There are three attributes associated with the class: + + * :attr:`initial_layout` - This attribute is used to model the + permutation caused by the :ref:`layout_stage` it contains a + :class:`~.Layout` object that maps the input :class:`~.QuantumCircuit`\s + :class:`~.Qubit` objects to the position in the output + :class:`.QuantumCircuit.qubits` list. + * :attr:`input_qubit_mapping` - This attribute is used to retain + input ordering of the original :class:`~.QuantumCircuit` object. It + maps the virtual :class:`~.Qubit` object from the original circuit + (and :attr:`initial_layout`) to its corresponding position in + :attr:`.QuantumCircuit.qubits` in the original circuit. This + is needed when computing the permutation of the :class:`Operator` of + the circuit (and used by :meth:`.Operator.from_circuit`). + * :attr:`final_layout` - This is a :class:`~.Layout` object used to + model the output permutation caused ny any :class:`~.SwapGate`\s + inserted into the :class:~.QuantumCircuit` during the + :ref:`routing_stage`. It maps the output circuit's qubits from + :class:`.QuantumCircuit.qubits` to the final position after + routing. + """ initial_layout: Layout input_qubit_mapping: Dict[Qubit, int] diff --git a/releasenotes/notes/add-layout-attribute-c84e56c08ca93ada.yaml b/releasenotes/notes/add-layout-attribute-c84e56c08ca93ada.yaml new file mode 100644 index 000000000000..b08f699c583e --- /dev/null +++ b/releasenotes/notes/add-layout-attribute-c84e56c08ca93ada.yaml @@ -0,0 +1,10 @@ +--- +features: + - | + Added a new attribute, :attr:`~.QuantumCircuit.layout`, to the + :class:`~.QuantumCircuit` class. This attribute is typically populated + by :func:`~.transpile` or :class:`.PassManager.run` (when the + :ref:`layout_stage` and :ref:`routing_stage` are run in the + :class:`~PassManager`) and contains a :class:`~.TranspileLayout` which + contains the information about the permutation of the input circuit + during :class:`~.transpile`.