From e7267548c32963c414de1c2f854e6de14f2c3b91 Mon Sep 17 00:00:00 2001 From: SimonR99 Date: Thu, 19 Oct 2023 23:57:06 -0400 Subject: [PATCH 1/5] List support for coupling map in pass manager --- .../preset_passmanagers/__init__.py | 10 +++++- .../transpiler/test_preset_passmanagers.py | 35 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/preset_passmanagers/__init__.py b/qiskit/transpiler/preset_passmanagers/__init__.py index bec81501aab5..752c0278a105 100644 --- a/qiskit/transpiler/preset_passmanagers/__init__.py +++ b/qiskit/transpiler/preset_passmanagers/__init__.py @@ -61,6 +61,7 @@ from qiskit.transpiler.passmanager_config import PassManagerConfig from qiskit.transpiler.target import target_to_backend_properties +from qiskit.transpiler import CouplingMap from .level0 import level_0_pass_manager from .level1 import level_1_pass_manager @@ -130,7 +131,7 @@ def generate_preset_pass_manager( circuit, transpiler attaches the custom gate definition to the circuit. This enables one to flexibly override the low-level instruction implementation. - coupling_map (CouplingMap): Directed graph represented a coupling + coupling_map (CouplingMap or list): Directed graph represented a coupling map. instruction_durations (InstructionDurations): Dictionary of duration (in dt) for each instruction. @@ -213,6 +214,13 @@ def generate_preset_pass_manager( stacklevel=2, ) + if ( + coupling_map + and isinstance(coupling_map, list) + and all(isinstance(sublist, list) for sublist in coupling_map) + ): + coupling_map = CouplingMap(coupling_map) + if target is not None: if coupling_map is None: coupling_map = target.build_coupling_map() diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index c1df58eb03cf..4c77b345f851 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -1272,7 +1272,7 @@ def test_size_optimization(self, level): @ddt -class TestGeenratePresetPassManagers(QiskitTestCase): +class TestGeneratePresetPassManagers(QiskitTestCase): """Test generate_preset_pass_manager function.""" @data(0, 1, 2, 3) @@ -1445,6 +1445,39 @@ def get_translation_stage_plugin(self): ] self.assertIn("RemoveResetInZeroState", post_translation_pass_list) + def test_generate_preset_pass_manager_with_list_coupling_map(self): + """Test that generate_preset_pass_manager can handle list-based coupling_map.""" + + # Define the coupling map as a list + coupling_map_list = [[0, 1]] + coupling_map_object = CouplingMap(coupling_map_list) + + # Circuit that doesn't fit in the coupling map + qc = QuantumCircuit(2) + qc.h(0) + qc.cx(0, 1) + qc.cx(1, 0) + qc.measure_all() + + pm_list = generate_preset_pass_manager(optimization_level=0, coupling_map=coupling_map_list) + pm_object = generate_preset_pass_manager( + optimization_level=0, coupling_map=coupling_map_object + ) + + transpiled_circuit_list = pm_list.run(qc) + transpiled_circuit_object = pm_object.run(qc) + + # Convert the transpiled circuits to DAGs to compare the states + dag_list = circuit_to_dag(transpiled_circuit_list) + dag_object = circuit_to_dag(transpiled_circuit_object) + + # Check if both are instances of PassManager + self.assertIsInstance(pm_list, PassManager) + self.assertIsInstance(pm_object, PassManager) + + # Ensure the DAGs from both methods are identical + self.assertEqual(dag_list, dag_object) + @ddt class TestIntegrationControlFlow(QiskitTestCase): From 12f8d9ce17e929e8866229935e6fcfec6a71989e Mon Sep 17 00:00:00 2001 From: SimonR99 Date: Fri, 20 Oct 2023 09:11:32 -0400 Subject: [PATCH 2/5] remove redundant checks for coupling list in preset pass manager --- .../preset_passmanagers/__init__.py | 6 +- ...manager-coupling-map-89e588e4260cb214.yaml | 7 ++ ...manager-coupling-map-b4f2f0ed36f12ad3.yaml | 65 +++++++++++++++++++ .../transpiler/test_preset_passmanagers.py | 6 +- 4 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml create mode 100644 releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml diff --git a/qiskit/transpiler/preset_passmanagers/__init__.py b/qiskit/transpiler/preset_passmanagers/__init__.py index 752c0278a105..ee1e407ae87d 100644 --- a/qiskit/transpiler/preset_passmanagers/__init__.py +++ b/qiskit/transpiler/preset_passmanagers/__init__.py @@ -214,11 +214,7 @@ def generate_preset_pass_manager( stacklevel=2, ) - if ( - coupling_map - and isinstance(coupling_map, list) - and all(isinstance(sublist, list) for sublist in coupling_map) - ): + if coupling_map is not None and not isinstance(coupling_map, CouplingMap): coupling_map = CouplingMap(coupling_map) if target is not None: diff --git a/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml b/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml new file mode 100644 index 000000000000..6bdcd5bc62c2 --- /dev/null +++ b/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Enhanced the `generate_preset_pass_manager` function to allow users to + directly provide a coupling map as a list. Previously, users were required + to provide a coupling map as an object. This change streamlines the process, + making it easier to define coupling maps without the need for object creation. diff --git a/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml b/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml new file mode 100644 index 000000000000..5e93448a33ce --- /dev/null +++ b/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml @@ -0,0 +1,65 @@ +--- +prelude: > + Replace this text with content to appear at the top of the section for this + release. All of the prelude content is merged together and then rendered + separately from the items listed in other parts of the file, so the text + needs to be worded so that both the prelude and the other items make sense + when read independently. This may mean repeating some details. Not every + release note requires a prelude. Usually only notes describing major + features or adding release theme details should have a prelude. +features: + - | + List new features here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +issues: + - | + List known issues here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +upgrade: + - | + List upgrade notes here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +deprecations: + - | + List deprecations notes here, or remove this section. All of the list + items in this section are combined when the release notes are rendered, so + the text needs to be worded so that it does not depend on any information + only available in another section, such as the prelude. This may mean + repeating some details. +critical: + - | + Add critical notes here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +security: + - | + Add security notes here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +fixes: + - | + Add normal bug fixes here, or remove this section. All of the list items + in this section are combined when the release notes are rendered, so the + text needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. +other: + - | + Add other notes here, or remove this section. All of the list items in + this section are combined when the release notes are rendered, so the text + needs to be worded so that it does not depend on any information only + available in another section, such as the prelude. This may mean repeating + some details. diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index 4c77b345f851..f25c8552e422 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -1467,16 +1467,12 @@ def test_generate_preset_pass_manager_with_list_coupling_map(self): transpiled_circuit_list = pm_list.run(qc) transpiled_circuit_object = pm_object.run(qc) - # Convert the transpiled circuits to DAGs to compare the states - dag_list = circuit_to_dag(transpiled_circuit_list) - dag_object = circuit_to_dag(transpiled_circuit_object) - # Check if both are instances of PassManager self.assertIsInstance(pm_list, PassManager) self.assertIsInstance(pm_object, PassManager) # Ensure the DAGs from both methods are identical - self.assertEqual(dag_list, dag_object) + self.assertEqual(transpiled_circuit_list, transpiled_circuit_object) @ddt From f28b21c6dd25e992fa48c3fd8cd023301c619c5d Mon Sep 17 00:00:00 2001 From: SimonR99 Date: Fri, 20 Oct 2023 09:21:34 -0400 Subject: [PATCH 3/5] remove duplicate release note --- ...manager-coupling-map-b4f2f0ed36f12ad3.yaml | 65 ------------------- 1 file changed, 65 deletions(-) delete mode 100644 releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml diff --git a/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml b/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml deleted file mode 100644 index 5e93448a33ce..000000000000 --- a/releasenotes/notes/preset-passmanager-coupling-map-b4f2f0ed36f12ad3.yaml +++ /dev/null @@ -1,65 +0,0 @@ ---- -prelude: > - Replace this text with content to appear at the top of the section for this - release. All of the prelude content is merged together and then rendered - separately from the items listed in other parts of the file, so the text - needs to be worded so that both the prelude and the other items make sense - when read independently. This may mean repeating some details. Not every - release note requires a prelude. Usually only notes describing major - features or adding release theme details should have a prelude. -features: - - | - List new features here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -issues: - - | - List known issues here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -upgrade: - - | - List upgrade notes here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -deprecations: - - | - List deprecations notes here, or remove this section. All of the list - items in this section are combined when the release notes are rendered, so - the text needs to be worded so that it does not depend on any information - only available in another section, such as the prelude. This may mean - repeating some details. -critical: - - | - Add critical notes here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -security: - - | - Add security notes here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -fixes: - - | - Add normal bug fixes here, or remove this section. All of the list items - in this section are combined when the release notes are rendered, so the - text needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. -other: - - | - Add other notes here, or remove this section. All of the list items in - this section are combined when the release notes are rendered, so the text - needs to be worded so that it does not depend on any information only - available in another section, such as the prelude. This may mean repeating - some details. From 259d956b075b30253e33bcc468aeecb9ad6a18c5 Mon Sep 17 00:00:00 2001 From: SimonR99 Date: Fri, 20 Oct 2023 09:36:07 -0400 Subject: [PATCH 4/5] add seed to the coupling list test case --- test/python/transpiler/test_preset_passmanagers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/python/transpiler/test_preset_passmanagers.py b/test/python/transpiler/test_preset_passmanagers.py index f25c8552e422..d37d5c2cbaad 100644 --- a/test/python/transpiler/test_preset_passmanagers.py +++ b/test/python/transpiler/test_preset_passmanagers.py @@ -1459,9 +1459,11 @@ def test_generate_preset_pass_manager_with_list_coupling_map(self): qc.cx(1, 0) qc.measure_all() - pm_list = generate_preset_pass_manager(optimization_level=0, coupling_map=coupling_map_list) + pm_list = generate_preset_pass_manager( + optimization_level=0, coupling_map=coupling_map_list, seed_transpiler=42 + ) pm_object = generate_preset_pass_manager( - optimization_level=0, coupling_map=coupling_map_object + optimization_level=0, coupling_map=coupling_map_object, seed_transpiler=42 ) transpiled_circuit_list = pm_list.run(qc) From 57b246760027f08069a1c36f6917232ff2e9dbee Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Fri, 20 Oct 2023 14:53:07 +0100 Subject: [PATCH 5/5] Fix up release note --- .../preset-passmanager-coupling-map-89e588e4260cb214.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml b/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml index 6bdcd5bc62c2..5830a57d2e2d 100644 --- a/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml +++ b/releasenotes/notes/preset-passmanager-coupling-map-89e588e4260cb214.yaml @@ -1,7 +1,6 @@ --- features: - | - Enhanced the `generate_preset_pass_manager` function to allow users to - directly provide a coupling map as a list. Previously, users were required - to provide a coupling map as an object. This change streamlines the process, - making it easier to define coupling maps without the need for object creation. + Enhanced the :func:`.generate_preset_pass_manager` function to allow users to + provide a coupling map as a legacy-format list. Previously, users were required + to provide a :class:`.CouplingMap` object.