From 044fc5fa2984bdc89f2aa9733552e9a64d3e05aa Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 25 Oct 2019 13:57:43 -0400 Subject: [PATCH 01/14] initial commit --- qiskit/transpiler/passes/__init__.py | 1 + .../transpiler/passes/mapping/layout_score.py | 43 ++++++++ test/python/transpiler/test_layout_score.py | 103 ++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 qiskit/transpiler/passes/mapping/layout_score.py create mode 100644 test/python/transpiler/test_layout_score.py diff --git a/qiskit/transpiler/passes/__init__.py b/qiskit/transpiler/passes/__init__.py index 6125b884061a..f54afaa60a25 100644 --- a/qiskit/transpiler/passes/__init__.py +++ b/qiskit/transpiler/passes/__init__.py @@ -48,6 +48,7 @@ from .mapping.dense_layout import DenseLayout from .mapping.noise_adaptive_layout import NoiseAdaptiveLayout from .mapping.basic_swap import BasicSwap +from .mapping.layout_score import LayoutScore from .mapping.lookahead_swap import LookaheadSwap from .remove_diagonal_gates_before_measure import RemoveDiagonalGatesBeforeMeasure from .mapping.stochastic_swap import StochasticSwap diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py new file mode 100644 index 000000000000..654393d43f4b --- /dev/null +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2019. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""A pass to evaluate how good the layout selection was. No CX direction is considered. +""" + +from qiskit.transpiler.basepasses import AnalysisPass + + +class LayoutScore(AnalysisPass): + def __init__(self, coupling_map, initial_layout=None): + super().__init__() + self.layout = initial_layout + self.coupling_map = coupling_map + + def run(self, dag): + self.layout = self.layout or self.property_set["layout"] + + if self.layout is None: + self.property_set['layout_score'] = None + return + + distances = [] + self.property_set['layout_score'] = 0 + + for gate in dag.twoQ_gates(): + physical_q0 = self.layout[gate.qargs[0]] + physical_q1 = self.layout[gate.qargs[1]] + + distances.append(self.coupling_map.distance(physical_q0, physical_q1)-1) + + self.property_set['layout_score'] += sum(distances) diff --git a/test/python/transpiler/test_layout_score.py b/test/python/transpiler/test_layout_score.py new file mode 100644 index 000000000000..be99077d7b49 --- /dev/null +++ b/test/python/transpiler/test_layout_score.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- + +# This code is part of Qiskit. +# +# (C) Copyright IBM 2019. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Test the Layout Score pass""" + +import unittest + +from qiskit import QuantumRegister, QuantumCircuit +from qiskit.transpiler.passes import LayoutScore +from qiskit.transpiler import CouplingMap, Layout +from qiskit.converters import circuit_to_dag +from qiskit.test import QiskitTestCase + + +class TestLayoutScoreError(QiskitTestCase): + def test_no_layout(self): + """No Layout. Empty Circuit CouplingMap map: None. Result: None + """ + qr = QuantumRegister(3, 'qr') + circuit = QuantumCircuit(qr) + coupling = CouplingMap() + layout = None + + dag = circuit_to_dag(circuit) + pass_ = LayoutScore(coupling, layout) + pass_.run(dag) + + self.assertIsNone(pass_.property_set['layout_score']) + +class TestTrivialLayoutScore(QiskitTestCase): + """ Trivial layout scenarios""" + + def test_no_cx(self): + """Empty Circuit CouplingMap map: None. Result: 0 + """ + qr = QuantumRegister(3, 'qr') + circuit = QuantumCircuit(qr) + coupling = CouplingMap() + layout = Layout().generate_trivial_layout(qr) + + dag = circuit_to_dag(circuit) + pass_ = LayoutScore(coupling, layout) + pass_.run(dag) + + self.assertEqual(pass_.property_set['layout_score'], 0) + + def test_swap_mapped_true(self): + """ Mapped circuit. Good Layout + qr0 (0):--(+)---(+)- + | | + qr1 (1):---.-----|-- + | + qr2 (2):---------.-- + + CouplingMap map: [1]--[0]--[2] + """ + qr = QuantumRegister(3, 'qr') + circuit = QuantumCircuit(qr) + circuit.cx(qr[0], qr[1]) + circuit.cx(qr[0], qr[2]) + coupling = CouplingMap([[0, 1], [0, 2]]) + layout = Layout().generate_trivial_layout(qr) + + dag = circuit_to_dag(circuit) + pass_ = LayoutScore(coupling, layout) + pass_.run(dag) + + self.assertEqual(pass_.property_set['layout_score'], 0) + + def test_swap_mapped_false(self): + """ Needs [0]-[1] in a [0]--[2]--[1] Result:1 + qr0:--(+)-- + | + qr1:---.--- + + CouplingMap map: [0]--[2]--[1] + """ + qr = QuantumRegister(2, 'qr') + circuit = QuantumCircuit(qr) + circuit.cx(qr[0], qr[1]) + coupling = CouplingMap([[0, 2], [2, 1]]) + layout = Layout().generate_trivial_layout(qr) + + dag = circuit_to_dag(circuit) + pass_ = LayoutScore(coupling, layout) + pass_.run(dag) + + self.assertEqual(pass_.property_set['layout_score'], 1) + + +if __name__ == '__main__': + unittest.main() From 9a7428d3223ecaab0f1276a58c0fefe1893a71c8 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 25 Oct 2019 14:12:29 -0400 Subject: [PATCH 02/14] docstring --- qiskit/transpiler/passes/mapping/layout_score.py | 4 +++- test/python/transpiler/test_layout_score.py | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index 654393d43f4b..b40cc71c6d5e 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -19,6 +19,9 @@ class LayoutScore(AnalysisPass): + """ + Saves in `layout_score` the sum of the . + """ def __init__(self, coupling_map, initial_layout=None): super().__init__() self.layout = initial_layout @@ -28,7 +31,6 @@ def run(self, dag): self.layout = self.layout or self.property_set["layout"] if self.layout is None: - self.property_set['layout_score'] = None return distances = [] diff --git a/test/python/transpiler/test_layout_score.py b/test/python/transpiler/test_layout_score.py index be99077d7b49..b6bb077c282b 100644 --- a/test/python/transpiler/test_layout_score.py +++ b/test/python/transpiler/test_layout_score.py @@ -24,6 +24,8 @@ class TestLayoutScoreError(QiskitTestCase): + """Test error-ish of Layout Score""" + def test_no_layout(self): """No Layout. Empty Circuit CouplingMap map: None. Result: None """ @@ -38,6 +40,7 @@ def test_no_layout(self): self.assertIsNone(pass_.property_set['layout_score']) + class TestTrivialLayoutScore(QiskitTestCase): """ Trivial layout scenarios""" From 30ed4d9cb89f9d845fe555291b585a8864ae4b9b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 25 Oct 2019 14:16:23 -0400 Subject: [PATCH 03/14] docstring --- qiskit/transpiler/passes/mapping/layout_score.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index b40cc71c6d5e..86c4b9e326ea 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -12,7 +12,11 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""A pass to evaluate how good the layout selection was. No CX direction is considered. +"""A pass to evaluate how good the layout selection was. +No CX direction is considered. +Saves in `layout_score` the sum of the distance off for each CX. +The lower the number, the better the selection. +Therefore, 0 is a perfect layout selection. """ from qiskit.transpiler.basepasses import AnalysisPass @@ -20,7 +24,7 @@ class LayoutScore(AnalysisPass): """ - Saves in `layout_score` the sum of the . + Saves in `layout_score` the sum of the distance off for each CX. """ def __init__(self, coupling_map, initial_layout=None): super().__init__() From fccad46549acac3d9918e6a48f20dc5e2387f09b Mon Sep 17 00:00:00 2001 From: Luciano Date: Sun, 27 Oct 2019 14:50:43 -0400 Subject: [PATCH 04/14] Update qiskit/transpiler/passes/mapping/layout_score.py Co-Authored-By: Ali Javadi-Abhari --- qiskit/transpiler/passes/mapping/layout_score.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index 86c4b9e326ea..7131ec3d3378 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -14,7 +14,7 @@ """A pass to evaluate how good the layout selection was. No CX direction is considered. -Saves in `layout_score` the sum of the distance off for each CX. +Saves in property_set[`layout_score`] the sum of distances for each circuit CX. The lower the number, the better the selection. Therefore, 0 is a perfect layout selection. """ From ea87e660ce60463a9e9275cd93992da8115f6a02 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 28 Oct 2019 12:21:59 -0400 Subject: [PATCH 05/14] += -> = --- qiskit/transpiler/passes/mapping/layout_score.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index 7131ec3d3378..a3435a998d43 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -38,7 +38,6 @@ def run(self, dag): return distances = [] - self.property_set['layout_score'] = 0 for gate in dag.twoQ_gates(): physical_q0 = self.layout[gate.qargs[0]] @@ -46,4 +45,4 @@ def run(self, dag): distances.append(self.coupling_map.distance(physical_q0, physical_q1)-1) - self.property_set['layout_score'] += sum(distances) + self.property_set['layout_score'] = sum(distances) From a5d1a4a3f31ec2e5134acb1d4b1b7459622a0208 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Mon, 28 Oct 2019 12:32:21 -0400 Subject: [PATCH 06/14] docstring --- .../transpiler/passes/mapping/layout_score.py | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index a3435a998d43..b1a9b5d1dc2d 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -12,9 +12,10 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -"""A pass to evaluate how good the layout selection was. +"""Evaluate how good the layout selection was. + No CX direction is considered. -Saves in property_set[`layout_score`] the sum of distances for each circuit CX. +Saves in `property_set['layout_score']` the sum of distances for each circuit CX. The lower the number, the better the selection. Therefore, 0 is a perfect layout selection. """ @@ -23,15 +24,29 @@ class LayoutScore(AnalysisPass): - """ - Saves in `layout_score` the sum of the distance off for each CX. + """Evaluate how good the layout selection was. + + Saves in `property_set['layout_score']` the sum of distances for each circuit CX. + The lower the number, the better the selection. Therefore, 0 is a perfect layout selection. + No CX direction is considered. """ def __init__(self, coupling_map, initial_layout=None): + """LayoutScore initializer. + + Args: + coupling_map (CouplingMap): Directed graph represented a coupling map. + initial_layout (Layout): The layout to evaluate. + """ super().__init__() self.layout = initial_layout self.coupling_map = coupling_map def run(self, dag): + """ + Run the LayoutScore pass on `dag`. + Args: + dag (DAGCircuit): DAG to evaluate. + """ self.layout = self.layout or self.property_set["layout"] if self.layout is None: From 9b8603b432608efd11b9a7428de25c69a997894e Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Wed, 30 Oct 2019 12:40:20 -0400 Subject: [PATCH 07/14] remove initial_layout param --- qiskit/transpiler/passes/mapping/layout_score.py | 12 +++++------- test/python/transpiler/test_layout_score.py | 12 ++++++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_score.py index b1a9b5d1dc2d..c37c5f6d1389 100644 --- a/qiskit/transpiler/passes/mapping/layout_score.py +++ b/qiskit/transpiler/passes/mapping/layout_score.py @@ -30,15 +30,13 @@ class LayoutScore(AnalysisPass): The lower the number, the better the selection. Therefore, 0 is a perfect layout selection. No CX direction is considered. """ - def __init__(self, coupling_map, initial_layout=None): + def __init__(self, coupling_map): """LayoutScore initializer. Args: coupling_map (CouplingMap): Directed graph represented a coupling map. - initial_layout (Layout): The layout to evaluate. """ super().__init__() - self.layout = initial_layout self.coupling_map = coupling_map def run(self, dag): @@ -47,16 +45,16 @@ def run(self, dag): Args: dag (DAGCircuit): DAG to evaluate. """ - self.layout = self.layout or self.property_set["layout"] + layout = self.property_set["layout"] - if self.layout is None: + if layout is None: return distances = [] for gate in dag.twoQ_gates(): - physical_q0 = self.layout[gate.qargs[0]] - physical_q1 = self.layout[gate.qargs[1]] + physical_q0 = layout[gate.qargs[0]] + physical_q1 = layout[gate.qargs[1]] distances.append(self.coupling_map.distance(physical_q0, physical_q1)-1) diff --git a/test/python/transpiler/test_layout_score.py b/test/python/transpiler/test_layout_score.py index b6bb077c282b..0e6b641e7c3f 100644 --- a/test/python/transpiler/test_layout_score.py +++ b/test/python/transpiler/test_layout_score.py @@ -35,7 +35,8 @@ def test_no_layout(self): layout = None dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling, layout) + pass_ = LayoutScore(coupling) + pass_.property_set['layout'] = layout pass_.run(dag) self.assertIsNone(pass_.property_set['layout_score']) @@ -53,7 +54,8 @@ def test_no_cx(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling, layout) + pass_ = LayoutScore(coupling) + pass_.property_set['layout'] = layout pass_.run(dag) self.assertEqual(pass_.property_set['layout_score'], 0) @@ -76,7 +78,8 @@ def test_swap_mapped_true(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling, layout) + pass_ = LayoutScore(coupling) + pass_.property_set['layout'] = layout pass_.run(dag) self.assertEqual(pass_.property_set['layout_score'], 0) @@ -96,7 +99,8 @@ def test_swap_mapped_false(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling, layout) + pass_ = LayoutScore(coupling) + pass_.property_set['layout'] = layout pass_.run(dag) self.assertEqual(pass_.property_set['layout_score'], 1) From c8cfd3d571c1beaa115acdaa8cbd13ce67b3defd Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 16:31:06 -0400 Subject: [PATCH 08/14] rename qiskit/transpiler/passes/mapping/layout_score.py qiskit/transpiler/passes/mapping/layout_2q_distance.py --- .../passes/mapping/{layout_score.py => layout_2q_distance.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename qiskit/transpiler/passes/mapping/{layout_score.py => layout_2q_distance.py} (100%) diff --git a/qiskit/transpiler/passes/mapping/layout_score.py b/qiskit/transpiler/passes/mapping/layout_2q_distance.py similarity index 100% rename from qiskit/transpiler/passes/mapping/layout_score.py rename to qiskit/transpiler/passes/mapping/layout_2q_distance.py From 4f7a743038f747402dea2896c9f803f3df7934fa Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 16:41:37 -0400 Subject: [PATCH 09/14] LayoutScore -> Layout2qDistance --- qiskit/transpiler/passes/__init__.py | 2 +- qiskit/transpiler/passes/mapping/layout_2q_distance.py | 6 +++--- test/python/transpiler/test_layout_score.py | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/qiskit/transpiler/passes/__init__.py b/qiskit/transpiler/passes/__init__.py index f54afaa60a25..e0ae22a7ec1e 100644 --- a/qiskit/transpiler/passes/__init__.py +++ b/qiskit/transpiler/passes/__init__.py @@ -48,7 +48,7 @@ from .mapping.dense_layout import DenseLayout from .mapping.noise_adaptive_layout import NoiseAdaptiveLayout from .mapping.basic_swap import BasicSwap -from .mapping.layout_score import LayoutScore +from .mapping.layout_2q_distance import Layout2qDistance from .mapping.lookahead_swap import LookaheadSwap from .remove_diagonal_gates_before_measure import RemoveDiagonalGatesBeforeMeasure from .mapping.stochastic_swap import StochasticSwap diff --git a/qiskit/transpiler/passes/mapping/layout_2q_distance.py b/qiskit/transpiler/passes/mapping/layout_2q_distance.py index c37c5f6d1389..5182f2e68791 100644 --- a/qiskit/transpiler/passes/mapping/layout_2q_distance.py +++ b/qiskit/transpiler/passes/mapping/layout_2q_distance.py @@ -23,7 +23,7 @@ from qiskit.transpiler.basepasses import AnalysisPass -class LayoutScore(AnalysisPass): +class Layout2qDistance(AnalysisPass): """Evaluate how good the layout selection was. Saves in `property_set['layout_score']` the sum of distances for each circuit CX. @@ -31,7 +31,7 @@ class LayoutScore(AnalysisPass): No CX direction is considered. """ def __init__(self, coupling_map): - """LayoutScore initializer. + """Layout2qDistance initializer. Args: coupling_map (CouplingMap): Directed graph represented a coupling map. @@ -41,7 +41,7 @@ def __init__(self, coupling_map): def run(self, dag): """ - Run the LayoutScore pass on `dag`. + Run the Layout2qDistance pass on `dag`. Args: dag (DAGCircuit): DAG to evaluate. """ diff --git a/test/python/transpiler/test_layout_score.py b/test/python/transpiler/test_layout_score.py index 0e6b641e7c3f..a9f524c55948 100644 --- a/test/python/transpiler/test_layout_score.py +++ b/test/python/transpiler/test_layout_score.py @@ -17,7 +17,7 @@ import unittest from qiskit import QuantumRegister, QuantumCircuit -from qiskit.transpiler.passes import LayoutScore +from qiskit.transpiler.passes import Layout2qDistance from qiskit.transpiler import CouplingMap, Layout from qiskit.converters import circuit_to_dag from qiskit.test import QiskitTestCase @@ -35,7 +35,7 @@ def test_no_layout(self): layout = None dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling) + pass_ = Layout2qDistance(coupling) pass_.property_set['layout'] = layout pass_.run(dag) @@ -54,7 +54,7 @@ def test_no_cx(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling) + pass_ = Layout2qDistance(coupling) pass_.property_set['layout'] = layout pass_.run(dag) @@ -78,7 +78,7 @@ def test_swap_mapped_true(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling) + pass_ = Layout2qDistance(coupling) pass_.property_set['layout'] = layout pass_.run(dag) @@ -99,7 +99,7 @@ def test_swap_mapped_false(self): layout = Layout().generate_trivial_layout(qr) dag = circuit_to_dag(circuit) - pass_ = LayoutScore(coupling) + pass_ = Layout2qDistance(coupling) pass_.property_set['layout'] = layout pass_.run(dag) From c852aaf17042bb00f7b12e196d6e96d65ed8cbea Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 16:45:14 -0400 Subject: [PATCH 10/14] counter --- qiskit/transpiler/passes/mapping/layout_2q_distance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_2q_distance.py b/qiskit/transpiler/passes/mapping/layout_2q_distance.py index 5182f2e68791..0f83725ee8d2 100644 --- a/qiskit/transpiler/passes/mapping/layout_2q_distance.py +++ b/qiskit/transpiler/passes/mapping/layout_2q_distance.py @@ -50,12 +50,12 @@ def run(self, dag): if layout is None: return - distances = [] + sum_distance = 0 for gate in dag.twoQ_gates(): physical_q0 = layout[gate.qargs[0]] physical_q1 = layout[gate.qargs[1]] - distances.append(self.coupling_map.distance(physical_q0, physical_q1)-1) + sum_distance += self.coupling_map.distance(physical_q0, physical_q1)-1 - self.property_set['layout_score'] = sum(distances) + self.property_set['layout_score'] = sum_distance From 147891ae301ed076d496cb44397a7480c3af6685 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Thu, 31 Oct 2019 16:59:05 -0400 Subject: [PATCH 11/14] dyn property name --- qiskit/transpiler/passes/mapping/layout_2q_distance.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/qiskit/transpiler/passes/mapping/layout_2q_distance.py b/qiskit/transpiler/passes/mapping/layout_2q_distance.py index 0f83725ee8d2..6ffda829f6c1 100644 --- a/qiskit/transpiler/passes/mapping/layout_2q_distance.py +++ b/qiskit/transpiler/passes/mapping/layout_2q_distance.py @@ -26,11 +26,12 @@ class Layout2qDistance(AnalysisPass): """Evaluate how good the layout selection was. - Saves in `property_set['layout_score']` the sum of distances for each circuit CX. + Saves in `property_set['layout_score']` (or the property name in property_name) + the sum of distances for each circuit CX. The lower the number, the better the selection. Therefore, 0 is a perfect layout selection. No CX direction is considered. """ - def __init__(self, coupling_map): + def __init__(self, coupling_map, property_name='layout_score'): """Layout2qDistance initializer. Args: @@ -38,6 +39,7 @@ def __init__(self, coupling_map): """ super().__init__() self.coupling_map = coupling_map + self.property_name = property_name def run(self, dag): """ @@ -58,4 +60,4 @@ def run(self, dag): sum_distance += self.coupling_map.distance(physical_q0, physical_q1)-1 - self.property_set['layout_score'] = sum_distance + self.property_set[self.property_name] = sum_distance From 25615364dbac00ede500adb8dd6b3e14eae552e2 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 1 Nov 2019 10:53:42 -0400 Subject: [PATCH 12/14] docstring --- qiskit/transpiler/passes/mapping/layout_2q_distance.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qiskit/transpiler/passes/mapping/layout_2q_distance.py b/qiskit/transpiler/passes/mapping/layout_2q_distance.py index 6ffda829f6c1..36eb2aa45763 100644 --- a/qiskit/transpiler/passes/mapping/layout_2q_distance.py +++ b/qiskit/transpiler/passes/mapping/layout_2q_distance.py @@ -36,6 +36,7 @@ def __init__(self, coupling_map, property_name='layout_score'): Args: coupling_map (CouplingMap): Directed graph represented a coupling map. + property_name (str): The property name to save the score. Default: layout_score """ super().__init__() self.coupling_map = coupling_map From ffd885ef430800bacb3a0e46026892c66a3fcb8b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 1 Nov 2019 16:12:10 -0400 Subject: [PATCH 13/14] release note --- .../Layout2qDistance-84fccae5eb89699c.yaml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml diff --git a/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml b/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml new file mode 100644 index 000000000000..d129ad93d9a4 --- /dev/null +++ b/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml @@ -0,0 +1,21 @@ +--- +features: + - | + A new analysis pass is added: ``Layout2qDistance``. This pass allows to "score" a + layout selection, once ``property_set['layout']`` is set. + The score will be the sum of distances for each entanglement in the circuit, + when they are not directly connected. + This scoring does not consider direction in the coupling map. + The lower the number, the better the layout selection is. + + For example, consider a linear coupling map ``[0]--[2]--[1]`` and the + following circuit: + + qr = QuantumRegister(2, 'qr') + circuit = QuantumCircuit(qr) + circuit.cx(qr[0], qr[1]) + + If the layout is ``{qr[0]:0, qr[1]:1}``, ``Layout2qDistance`` will set + ``property_set['layout_score'] = 1``. If the layout + is ``{qr[0]:0, qr[1]:2}``, then the result + is ``property_set['layout_score'] = 0``. The lower the score, the better. \ No newline at end of file From 4d071e23069c3170c064e8c2d92f2c91fdb1cded Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Fri, 1 Nov 2019 16:46:50 -0400 Subject: [PATCH 14/14] each two qubit gate in the circuit --- releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml b/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml index d129ad93d9a4..a3697bd7e002 100644 --- a/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml +++ b/releasenotes/notes/Layout2qDistance-84fccae5eb89699c.yaml @@ -3,7 +3,7 @@ features: - | A new analysis pass is added: ``Layout2qDistance``. This pass allows to "score" a layout selection, once ``property_set['layout']`` is set. - The score will be the sum of distances for each entanglement in the circuit, + The score will be the sum of distances for each two-qubit gate in the circuit, when they are not directly connected. This scoring does not consider direction in the coupling map. The lower the number, the better the layout selection is.