From 653837f7fc37b4615ea03e4099c6b003b5d12e39 Mon Sep 17 00:00:00 2001 From: "Christopher J. Wood" Date: Wed, 17 Jan 2024 12:59:15 -0500 Subject: [PATCH 1/5] Fix bugs with V2FLayout pass and Qiskit Aer 0.13 --- qiskit/transpiler/passes/layout/vf2_layout.py | 11 +++++++---- qiskit/transpiler/passes/layout/vf2_utils.py | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/qiskit/transpiler/passes/layout/vf2_layout.py b/qiskit/transpiler/passes/layout/vf2_layout.py index 4e3077eb1d4d..740a778cd68e 100644 --- a/qiskit/transpiler/passes/layout/vf2_layout.py +++ b/qiskit/transpiler/passes/layout/vf2_layout.py @@ -104,15 +104,18 @@ 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 it generates non-trivial values for these. 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 +148,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 From 57470f5a9e70435e5493613a435fe3fe78891396 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 7 Jun 2024 15:59:56 +0200 Subject: [PATCH 2/5] Update qiskit/transpiler/passes/layout/vf2_layout.py Co-authored-by: Matthew Treinish --- qiskit/transpiler/passes/layout/vf2_layout.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/passes/layout/vf2_layout.py b/qiskit/transpiler/passes/layout/vf2_layout.py index 740a778cd68e..e958410865ee 100644 --- a/qiskit/transpiler/passes/layout/vf2_layout.py +++ b/qiskit/transpiler/passes/layout/vf2_layout.py @@ -104,7 +104,9 @@ 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`` if it generates non-trivial values for these. + ``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. From 25fb59fd9cc18059d8cbda7397107b67eb3b5469 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 7 Jun 2024 16:02:53 +0200 Subject: [PATCH 3/5] test --- .../notes/fix-vf2-aer-a7306ce07ea81700.yaml | 4 ++++ test/python/transpiler/test_vf2_layout.py | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml diff --git a/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml new file mode 100644 index 000000000000..f967897e3b2d --- /dev/null +++ b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml @@ -0,0 +1,4 @@ +fixes: + - | + The :class:`.VF2Layout` pass was raise an exception incorrectly when a :class:`.Target` without a coupling map is provided. + With Aer 0.13, this situation is the case. diff --git a/test/python/transpiler/test_vf2_layout.py b/test/python/transpiler/test_vf2_layout.py index b0957c824688..716e49d35009 100644 --- a/test/python/transpiler/test_vf2_layout.py +++ b/test/python/transpiler/test_vf2_layout.py @@ -570,6 +570,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.""" From 59b0eaf465966a317fee1df9b8ebe998d16e5e45 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sat, 8 Jun 2024 07:55:56 +0200 Subject: [PATCH 4/5] Update releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml index f967897e3b2d..52ea96d0984b 100644 --- a/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml +++ b/releasenotes/notes/fix-vf2-aer-a7306ce07ea81700.yaml @@ -1,4 +1,4 @@ fixes: - | - The :class:`.VF2Layout` pass was raise an exception incorrectly when a :class:`.Target` without a coupling map is provided. - With Aer 0.13, this situation is the case. + 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. From 13789a49207f7b05bf97542d14356a1034195d32 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Sat, 8 Jun 2024 07:57:41 +0200 Subject: [PATCH 5/5] long lines --- qiskit/transpiler/passes/layout/vf2_layout.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/passes/layout/vf2_layout.py b/qiskit/transpiler/passes/layout/vf2_layout.py index e958410865ee..626f8f2b0fa3 100644 --- a/qiskit/transpiler/passes/layout/vf2_layout.py +++ b/qiskit/transpiler/passes/layout/vf2_layout.py @@ -104,8 +104,9 @@ 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`` 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`` + ``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: