From 601bc55d279d3b56096a014b5462fc0b62d93c66 Mon Sep 17 00:00:00 2001 From: "Christopher J. Wood" Date: Mon, 10 Jun 2024 04:39:57 -0400 Subject: [PATCH] Fix bugs with VF2Layout pass and Qiskit Aer 0.13 (#11585) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix bugs with V2FLayout pass and Qiskit Aer 0.13 * Update qiskit/transpiler/passes/layout/vf2_layout.py Co-authored-by: Matthew Treinish * test * Update releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> * long lines --------- Co-authored-by: Luciano Bello Co-authored-by: Matthew Treinish Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> (cherry picked from commit 2b847b8e9b8ca21e6c0e1ce26acb0686aec3175a) --- qiskit/transpiler/passes/layout/vf2_layout.py | 14 +++++++++---- qiskit/transpiler/passes/layout/vf2_utils.py | 4 ++-- .../notes/fix-vf2-aer-a7306ce07ea81700.yaml | 4 ++++ test/python/transpiler/test_vf2_layout.py | 20 +++++++++++++++++++ 4 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml diff --git a/qiskit/transpiler/passes/layout/vf2_layout.py b/qiskit/transpiler/passes/layout/vf2_layout.py index 4e3077eb1d4d..626f8f2b0fa3 100644 --- a/qiskit/transpiler/passes/layout/vf2_layout.py +++ b/qiskit/transpiler/passes/layout/vf2_layout.py @@ -104,15 +104,21 @@ def __init__( limit on the number of trials will be set. target (Target): A target representing the backend device to run ``VF2Layout`` on. If specified it will supersede a set value for ``properties`` and - ``coupling_map``. + ``coupling_map`` if the :class:`.Target` contains connectivity constraints. If the value + of ``target`` models an ideal backend without any constraints then the value of + ``coupling_map`` + will be used. Raises: TypeError: At runtime, if neither ``coupling_map`` or ``target`` are provided. """ super().__init__() self.target = target - if target is not None: - self.coupling_map = self.target.build_coupling_map() + if ( + target is not None + and (target_coupling_map := self.target.build_coupling_map()) is not None + ): + self.coupling_map = target_coupling_map else: self.coupling_map = coupling_map self.properties = properties @@ -145,7 +151,7 @@ def run(self, dag): ) # Filter qubits without any supported operations. If they don't support any operations # They're not valid for layout selection - if self.target is not None: + if self.target is not None and self.target.qargs is not None: has_operations = set(itertools.chain.from_iterable(self.target.qargs)) to_remove = set(range(len(cm_nodes))).difference(has_operations) if to_remove: diff --git a/qiskit/transpiler/passes/layout/vf2_utils.py b/qiskit/transpiler/passes/layout/vf2_utils.py index 99006017482c..c5d420127f88 100644 --- a/qiskit/transpiler/passes/layout/vf2_utils.py +++ b/qiskit/transpiler/passes/layout/vf2_utils.py @@ -145,7 +145,7 @@ def score_layout( def build_average_error_map(target, properties, coupling_map): """Build an average error map used for scoring layouts pre-basis translation.""" num_qubits = 0 - if target is not None: + if target is not None and target.qargs is not None: num_qubits = target.num_qubits avg_map = ErrorMap(len(target.qargs)) elif coupling_map is not None: @@ -157,7 +157,7 @@ def build_average_error_map(target, properties, coupling_map): # object avg_map = ErrorMap(0) built = False - if target is not None: + if target is not None and target.qargs is not None: for qargs in target.qargs: if qargs is None: continue diff --git a/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml new file mode 100644 index 000000000000..52ea96d0984b --- /dev/null +++ b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml @@ -0,0 +1,4 @@ +fixes: + - | + The :class:`.VF2Layout` pass would raise an exception when provided with a :class:`.Target` instance without connectivity constraints. + This would be the case with targets from Aer 0.13. The issue is now fixed. diff --git a/test/python/transpiler/test_vf2_layout.py b/test/python/transpiler/test_vf2_layout.py index b1eb02a489d9..8e534aee66fc 100644 --- a/test/python/transpiler/test_vf2_layout.py +++ b/test/python/transpiler/test_vf2_layout.py @@ -576,6 +576,26 @@ def test_3_q_gate(self): pass_1.property_set["VF2Layout_stop_reason"], VF2LayoutStopReason.MORE_THAN_2Q ) + def test_target_without_coupling_map(self): + """When a target has no coupling_map but it is provided as argument. + See: https://github.com/Qiskit/qiskit/pull/11585""" + + circuit = QuantumCircuit(3) + circuit.cx(0, 1) + dag = circuit_to_dag(circuit) + + target = Target(num_qubits=3) + target.add_instruction(CXGate()) + + vf2_pass = VF2Layout( + coupling_map=CouplingMap([[0, 2], [1, 2]]), target=target, seed=42, max_trials=1 + ) + vf2_pass.run(dag) + + self.assertEqual( + vf2_pass.property_set["VF2Layout_stop_reason"], VF2LayoutStopReason.SOLUTION_FOUND + ) + class TestMultipleTrials(QiskitTestCase): """Test the passes behavior with >1 trial."""