From f9c4436bfb466e90860226c495c568cc9e83b9cb Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 12 Apr 2022 10:11:21 -0400 Subject: [PATCH 1/4] Fix dag visualization for DAGCircuits without registers This commit fixes the handling of generating visualizations for DAGCircuit objects that have standalone bit objects. Previously, the dag_drawer() function was assuming every bit in the dag was a member of a register. In the case of circuits with standalone bits this is not the case and would result in a KeyError being raised when the register was attempted to be used to generate a string label for the node or edge in the visualization. This fixes this by still using registers if present, but in the absence of a register it fallsback to using it's absolute index in the dag to generate a similar label. For example, the 4th qubit will have the label "q[4]" in the output visualization. Fixes #7915 --- qiskit/visualization/dag_visualization.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/qiskit/visualization/dag_visualization.py b/qiskit/visualization/dag_visualization.py index 80a01e03a83..2e6ecde9d3b 100644 --- a/qiskit/visualization/dag_visualization.py +++ b/qiskit/visualization/dag_visualization.py @@ -21,6 +21,7 @@ import tempfile from qiskit.dagcircuit.dagnode import DAGOpNode, DAGInNode, DAGOutNode +from qiskit.circuit import Qubit from qiskit.utils import optionals as _optionals from qiskit.exceptions import InvalidFileError from .exceptions import VisualizationError @@ -173,7 +174,9 @@ def node_attr_func(node): edge_attr_func = None else: - bit_labels = { + qubit_indices = {bit: index for index, bit in enumerate(dag.qubits)} + clbit_indices = {bit: index for index, bit in enumerate(dag.clbits)} + register_bit_labels = { bit: f"{reg.name}[{idx}]" for reg in list(dag.qregs.values()) + list(dag.cregs.values()) for (idx, bit) in enumerate(reg) @@ -192,12 +195,20 @@ def node_attr_func(node): n["style"] = "filled" n["fillcolor"] = "lightblue" if isinstance(node, DAGInNode): - n["label"] = bit_labels[node.wire] + if isinstance(node.wire, Qubit): + label = register_bit_labels.get(node.wire, f"q[{qubit_indices[node.wire]}]") + else: + label = register_bit_labels.get(node.wire, f"c[{clbit_indices[node.wire]}]") + n["label"] = label n["color"] = "black" n["style"] = "filled" n["fillcolor"] = "green" if isinstance(node, DAGOutNode): - n["label"] = bit_labels[node.wire] + if isinstance(node.wire, Qubit): + label = register_bit_labels.get(node.wire, f"q[{qubit_indices[node.wire]}]") + else: + label = register_bit_labels.get(node.wire, f"c[{clbit_indices[node.wire]}]") + n["label"] = label n["color"] = "black" n["style"] = "filled" n["fillcolor"] = "red" @@ -207,7 +218,11 @@ def node_attr_func(node): def edge_attr_func(edge): e = {} - e["label"] = bit_labels[edge] + if isinstance(edge, Qubit): + label = register_bit_labels.get(edge, f"q[{qubit_indices[edge]}]") + else: + label = register_bit_labels.get(edge, f"c[{clbit_indices[edge]}]") + e["label"] = label return e dot_str = dag._multi_graph.to_dot(node_attr_func, edge_attr_func, graph_attrs) From c8b7ecca74420f5c213cb31a0df9b306ecadb3f9 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 12 Apr 2022 12:29:29 -0400 Subject: [PATCH 2/4] Adjust default label from q[0] to q_0 This commit changes the default fallback label when no register match is found to be of the form q_0, where 0 is the qubit index. This was done to avoid potential confusion with a register named q which might be in the circuit and not the first element in the qubits list. --- qiskit/visualization/dag_visualization.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qiskit/visualization/dag_visualization.py b/qiskit/visualization/dag_visualization.py index 2e6ecde9d3b..327f9f172de 100644 --- a/qiskit/visualization/dag_visualization.py +++ b/qiskit/visualization/dag_visualization.py @@ -196,9 +196,9 @@ def node_attr_func(node): n["fillcolor"] = "lightblue" if isinstance(node, DAGInNode): if isinstance(node.wire, Qubit): - label = register_bit_labels.get(node.wire, f"q[{qubit_indices[node.wire]}]") + label = register_bit_labels.get(node.wire, f"q_{qubit_indices[node.wire]}") else: - label = register_bit_labels.get(node.wire, f"c[{clbit_indices[node.wire]}]") + label = register_bit_labels.get(node.wire, f"c_{clbit_indices[node.wire]}") n["label"] = label n["color"] = "black" n["style"] = "filled" @@ -219,9 +219,9 @@ def node_attr_func(node): def edge_attr_func(edge): e = {} if isinstance(edge, Qubit): - label = register_bit_labels.get(edge, f"q[{qubit_indices[edge]}]") + label = register_bit_labels.get(edge, f"q_{qubit_indices[edge]}") else: - label = register_bit_labels.get(edge, f"c[{clbit_indices[edge]}]") + label = register_bit_labels.get(edge, f"c_{clbit_indices[edge]}") e["label"] = label return e From ab9c792f368665a101c9bc699b29820f9c414732 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 12 Apr 2022 12:33:16 -0400 Subject: [PATCH 3/4] Add release note --- .../notes/fix-dag-drawer-no-reg-6eee9d1f6e4b9261.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 releasenotes/notes/fix-dag-drawer-no-reg-6eee9d1f6e4b9261.yaml diff --git a/releasenotes/notes/fix-dag-drawer-no-reg-6eee9d1f6e4b9261.yaml b/releasenotes/notes/fix-dag-drawer-no-reg-6eee9d1f6e4b9261.yaml new file mode 100644 index 00000000000..390834dea04 --- /dev/null +++ b/releasenotes/notes/fix-dag-drawer-no-reg-6eee9d1f6e4b9261.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fixed an issue with the visualization function :func:`~.dag_drawer` and the + :meth:`.DAGCircuit.draw` method where previously the drawer would fail + when attempting to generate a visualization for a :class:`~.DAGCircuit` + object that contained a :class:`~.Qubit` or :class:`~.Clbit` which wasn't + part of a :class:`~QuantumRegister` or :class:`~ClassicalRegister`. + Fixed `#7915 `__ From b324e51464eee1061a739559988989a3217d5ba8 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Tue, 12 Apr 2022 13:04:05 -0400 Subject: [PATCH 4/4] Add test --- .../visualization/references/dag_no_reg.png | Bin 0 -> 16758 bytes test/python/visualization/test_dag_drawer.py | 27 ++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/python/visualization/references/dag_no_reg.png diff --git a/test/python/visualization/references/dag_no_reg.png b/test/python/visualization/references/dag_no_reg.png new file mode 100644 index 0000000000000000000000000000000000000000..48f7324b5230e80f27487ffd55247e1cb1fe0a87 GIT binary patch literal 16758 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 literal 0 HcmV?d00001 diff --git a/test/python/visualization/test_dag_drawer.py b/test/python/visualization/test_dag_drawer.py index a34f9641106..eea4f94fb38 100644 --- a/test/python/visualization/test_dag_drawer.py +++ b/test/python/visualization/test_dag_drawer.py @@ -12,17 +12,22 @@ """Tests for DAG visualization tool.""" +import os +import tempfile import unittest -from qiskit import QuantumRegister, QuantumCircuit -from qiskit.test import QiskitTestCase +from PIL import Image + +from qiskit.circuit import QuantumRegister, QuantumCircuit, Qubit, Clbit from qiskit.tools.visualization import dag_drawer from qiskit.exceptions import InvalidFileError from qiskit.visualization.exceptions import VisualizationError from qiskit.converters import circuit_to_dag +from qiskit.utils import optionals as _optionals +from .visualization import path_to_diagram_reference, QiskitVisualizationTestCase -class TestDagDrawer(QiskitTestCase): +class TestDagDrawer(QiskitVisualizationTestCase): """Qiskit DAG drawer tests.""" def setUp(self): @@ -49,6 +54,22 @@ def test_dag_drawer_checks_filename_extension(self): with self.assertRaisesRegex(InvalidFileError, "Filename extension must be one of: .*"): dag_drawer(self.dag, filename="aa.abc") + @unittest.skipUnless(_optionals.HAS_GRAPHVIZ, "Graphviz not installed") + def test_dag_drawer_no_register(self): + """Test dag visualization with a circuit with no registers.""" + qubit = Qubit() + clbit = Clbit() + qc = QuantumCircuit([qubit, clbit]) + qc.h(0) + qc.measure(0, 0) + dag = circuit_to_dag(qc) + with tempfile.TemporaryDirectory() as tmpdirname: + tmp_path = os.path.join(tmpdirname, "dag.png") + dag_drawer(dag, filename=tmp_path) + image_ref = path_to_diagram_reference("dag_no_reg.png") + image = Image.open(tmp_path) + self.assertImagesAreEqual(image, image_ref, 0.2) + if __name__ == "__main__": unittest.main(verbosity=2)