Skip to content

Commit

Permalink
Fix issues with ControlFlowOp displays (#10842) (#10917)
Browse files Browse the repository at this point in the history
Cherry-picked version of only the MPL-drawer changes from the given
commit, since the text-drawer support for dynamic circuits is not in the
old version.

(cherry picked from commit 404df43)

Co-authored-by: Edwin Navarro <enavarro@comcast.net>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
  • Loading branch information
3 people authored Sep 29, 2023
1 parent 8d3fd88 commit 6046106
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 90 deletions.
193 changes: 116 additions & 77 deletions qiskit/visualization/circuit/matplotlib.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixed an issue with the matplotlib based visualization in the
:meth:`.QuantumCircuit.draw` method and the :func:`~.circuit_drawer`
function when visualizing circuits that had control flow instructions.
Previously in some situations, especially with a layout set, the output
visualization could have put gates inside a control flow block on the
wrong wires in the visualization.
Fixed `#10601 <https://github.com/Qiskit/qiskit-terra/issues/10601>`__
Binary file modified test/visual/mpl/circuit/references/fold_with_conditions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 101 additions & 13 deletions test/visual/mpl/circuit/test_circuit_matplotlib_drawer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from qiskit.test import QiskitTestCase
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
from qiskit.providers.fake_provider import FakeTenerife
from qiskit.providers.fake_provider import FakeTenerife, FakeBelemV2
from qiskit.visualization.circuit.circuit_visualization import _matplotlib_circuit_drawer
from qiskit.circuit.library import (
XGate,
Expand All @@ -39,7 +39,7 @@
)
from qiskit.circuit.library import MCXVChain
from qiskit.extensions import HamiltonianGate
from qiskit.circuit import Parameter, Qubit, Clbit
from qiskit.circuit import Parameter, Qubit, Clbit, SwitchCaseOp, IfElseOp
from qiskit.circuit.library import IQP
from qiskit.quantum_info.random import random_unitary
from qiskit.utils import optionals
Expand Down Expand Up @@ -1483,8 +1483,8 @@ def test_sidetext_with_condition(self):

def test_fold_with_conditions(self):
"""Test that gates with conditions draw correctly when folding"""
qr = QuantumRegister(3)
cr = ClassicalRegister(5)
qr = QuantumRegister(3, "qr")
cr = ClassicalRegister(5, "cr")
circuit = QuantumCircuit(qr, cr)

circuit.append(U1Gate(0).control(1), [1, 0]).c_if(cr, 1)
Expand Down Expand Up @@ -1595,7 +1595,7 @@ def test_if_op(self):
circuit.cx(0, 1)

fname = "if_op.png"
self.circuit_drawer(circuit, filename=fname)
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
Expand All @@ -1606,8 +1606,8 @@ def test_if_op(self):
)
self.assertGreaterEqual(ratio, 0.9999)

def test_if_else_op(self):
"""Test the IfElseOp with else"""
def test_if_else_op_bundle_false(self):
"""Test the IfElseOp with else with cregbundle False"""
qr = QuantumRegister(4, "q")
cr = ClassicalRegister(2, "cr")
circuit = QuantumCircuit(qr, cr)
Expand All @@ -1618,7 +1618,32 @@ def test_if_else_op(self):
with _else:
circuit.cx(0, 1)

fname = "if_else_op.png"
fname = "if_else_op_false.png"
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
self._reference_path(fname),
fname,
FAILURE_DIFF_DIR,
FAILURE_PREFIX,
)
self.assertGreaterEqual(ratio, 0.9999)

def test_if_else_op_bundle_true(self):
"""Test the IfElseOp with else with cregbundle True"""
qr = QuantumRegister(4, "q")
cr = ClassicalRegister(2, "cr")
circuit = QuantumCircuit(qr, cr)

circuit.h(0)
with circuit.if_test((cr[1], 1)) as _else:
circuit.h(0)
circuit.cx(0, 1)
with _else:
circuit.cx(0, 1)

fname = "if_else_op_true.png"
self.circuit_drawer(circuit, filename=fname)

ratio = VisualTestUtilities._save_diff(
Expand All @@ -1643,7 +1668,7 @@ def test_if_else_op_textbook_style(self):
circuit.cx(0, 1)

fname = "if_else_op_textbook.png"
self.circuit_drawer(circuit, style="textbook", filename=fname)
self.circuit_drawer(circuit, style="textbook", cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
Expand Down Expand Up @@ -1677,7 +1702,7 @@ def test_if_else_with_body(self):
circuit.x(0, label="X1i")

fname = "if_else_body.png"
self.circuit_drawer(circuit, filename=fname)
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
Expand Down Expand Up @@ -1827,7 +1852,7 @@ def test_while_loop_op(self):
circuit.x(0)

fname = "while_loop.png"
self.circuit_drawer(circuit, filename=fname)
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
Expand Down Expand Up @@ -1856,7 +1881,7 @@ def test_for_loop_op(self):
circuit.z(0)

fname = "for_loop.png"
self.circuit_drawer(circuit, filename=fname)
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
Expand Down Expand Up @@ -1888,8 +1913,71 @@ def test_switch_case_op(self):
circuit.h(0)

fname = "switch_case.png"
self.circuit_drawer(circuit, filename=fname)
self.circuit_drawer(circuit, cregbundle=False, filename=fname)

ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
self._reference_path(fname),
fname,
FAILURE_DIFF_DIR,
FAILURE_PREFIX,
)
self.assertGreaterEqual(ratio, 0.9999)

def test_control_flow_layout(self):
"""Test control flow with a layout set."""
qreg = QuantumRegister(2, "qr")
creg = ClassicalRegister(2, "cr")
qc = QuantumCircuit(qreg, creg)
qc.h([0, 1])
qc.h([0, 1])
qc.h([0, 1])
qc.measure([0, 1], [0, 1])
with qc.switch(creg) as case:
with case(0):
qc.z(0)
with case(1, 2):
qc.cx(0, 1)
with case(case.DEFAULT):
qc.h(0)
backend = FakeBelemV2()
backend.target.add_instruction(SwitchCaseOp, name="switch_case")
tqc = transpile(qc, backend, optimization_level=2, seed_transpiler=671_42)
fname = "layout_control_flow.png"
self.circuit_drawer(tqc, filename=fname)
ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
self._reference_path(fname),
fname,
FAILURE_DIFF_DIR,
FAILURE_PREFIX,
)
self.assertGreaterEqual(ratio, 0.9999)

def test_control_flow_nested_layout(self):
"""Test nested control flow with a layout set."""
qreg = QuantumRegister(2, "qr")
creg = ClassicalRegister(2, "cr")
qc = QuantumCircuit(qreg, creg)
qc.h([0, 1])
qc.h([0, 1])
qc.h([0, 1])
qc.measure([0, 1], [0, 1])
with qc.switch(creg) as case:
with case(0):
qc.z(0)
with case(1, 2):
with qc.if_test((creg[0], 0)):
qc.cx(0, 1)
with case(case.DEFAULT):
with qc.if_test((creg[1], 0)):
qc.h(0)
backend = FakeBelemV2()
backend.target.add_instruction(SwitchCaseOp, name="switch_case")
backend.target.add_instruction(IfElseOp, name="if_else")
tqc = transpile(qc, backend, optimization_level=2, seed_transpiler=671_42)
fname = "nested_layout_control_flow.png"
self.circuit_drawer(tqc, filename=fname)
ratio = VisualTestUtilities._save_diff(
self._image_path(fname),
self._reference_path(fname),
Expand Down

0 comments on commit 6046106

Please sign in to comment.