Skip to content

Commit

Permalink
Merge pull request #5 from Qiskit/main
Browse files Browse the repository at this point in the history
Fix measure with condition display in mpl and latex drawers (Qiskit#6822)
  • Loading branch information
sakibguy authored Sep 4, 2021
2 parents 8cfdf41 + 808e66d commit 0271b7f
Show file tree
Hide file tree
Showing 17 changed files with 229 additions and 172 deletions.
44 changes: 25 additions & 19 deletions qiskit/visualization/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from qiskit.circuit.library.standard_gates import SwapGate, XGate, ZGate, RZZGate, U1Gate, PhaseGate
from qiskit.circuit.measure import Measure
from qiskit.visualization.qcstyle import load_style
from qiskit.visualization import exceptions
from qiskit.circuit.tools.pi_check import pi_check
from .utils import get_gate_ctrl_text, get_param_str, generate_latex_label

Expand Down Expand Up @@ -394,6 +393,10 @@ def _build_latex_array(self):
for node in layer:
op = node.op
num_cols_op = 1
wire_list = [self.img_regs[qarg] for qarg in node.qargs]
if op.condition:
self._add_condition(op, wire_list, column)

if isinstance(op, Measure):
self._build_measure(node, column)

Expand All @@ -404,15 +407,11 @@ def _build_latex_array(self):
gate_text, _, _ = get_gate_ctrl_text(op, "latex", style=self._style)
gate_text += get_param_str(op, "latex", ndigits=4)
gate_text = generate_latex_label(gate_text)
wire_list = [self.img_regs[qarg] for qarg in node.qargs]
if node.cargs:
cwire_list = [self.img_regs[carg] for carg in node.cargs]
else:
cwire_list = []

if op.condition:
self._add_condition(op, wire_list, column)

if len(wire_list) == 1 and not node.cargs:
self._latex[wire_list[0]][column] = "\\gate{%s}" % gate_text

Expand Down Expand Up @@ -531,10 +530,8 @@ def _build_symmetric_gate(self, op, gate_text, wire_list, col):

def _build_measure(self, node, col):
"""Build a meter and the lines to the creg"""
if node.op.condition:
raise exceptions.VisualizationError("If controlled measures currently not supported.")

wire1 = self.img_regs[node.qargs[0]]
self._latex[wire1][col] = "\\meter"
if self.cregbundle:
wire2 = len(self.qubit_list)
cregindex = self.img_regs[node.cargs[0]] - wire2
Expand All @@ -544,17 +541,15 @@ def _build_measure(self, node, col):
wire2 += 1
else:
break
else:
wire2 = self.img_regs[node.cargs[0]]

self._latex[wire1][col] = "\\meter"
if self.cregbundle:
self._latex[wire2][col] = "\\dstick{_{_{%s}}} \\cw \\cwx[-%s]" % (
cond_offset = 1.5 if node.op.condition else 0.0
self._latex[wire2][col] = "\\dstick{_{_{\\hspace{%sem}%s}}} \\cw \\ar @{<=} [-%s,0]" % (
cond_offset,
str(cregindex),
str(wire2 - wire1),
)
else:
self._latex[wire2][col] = "\\control \\cw \\cwx[-" + str(wire2 - wire1) + "]"
wire2 = self.img_regs[node.cargs[0]]
self._latex[wire2][col] = "\\cw \\ar @{<=} [-" + str(wire2 - wire1) + ",0]"

def _build_barrier(self, node, col):
"""Build a partial or full barrier if plot_barriers set"""
Expand Down Expand Up @@ -612,18 +607,29 @@ def _add_condition(self, op, wire_list, col):
cwire += 1

gap = cwire - max(wire_list)
meas_offset = -0.3 if isinstance(op, Measure) else 0.0
if self.cregbundle:
# Print the condition value at the bottom
self._latex[cwire][col] = "\\dstick{_{_{=%s}}} \\cw \\cwx[-%s]" % (
str(op.condition[1]),
# Print the condition value at the bottom and put bullet on creg line
self._latex[cwire][col] = "\\control \\cw^(%s){^{\\mathtt{%s}}} \\cwx[-%s]" % (
meas_offset,
str(hex(op.condition[1])),
str(gap),
)
else:
# Add the open and closed buttons to indicate the condition value
for i in range(creg_size):
for i in range(creg_size - 1):
control = "\\control" if if_value[i] == "1" else "\\controlo"
self._latex[cwire + i][col] = f"{control} \\cw \\cwx[-" + str(gap) + "]"
gap = 1
# Add (hex condition value) below the last cwire
control = "\\control" if if_value[creg_size - 1] == "1" else "\\controlo"
self._latex[creg_size + cwire - 1][col] = (
f"{control}" + " \\cw^(%s){^{\\mathtt{%s}}} \\cwx[-%s]"
) % (
meas_offset,
str(hex(op.condition[1])),
str(gap),
)

def _truncate_float(self, matchobj, ndigits=4):
"""Truncate long floats."""
Expand Down
2 changes: 2 additions & 0 deletions qiskit/visualization/matplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ def _condition(self, node, cond_xy):
v_ind += 1
clbit_b = min(xy_plot, key=lambda xy: xy[1])
xpos, ypos = clbit_b
if isinstance(node.op, Measure):
xpos += 0.3
self._ax.text(
xpos,
ypos - 0.3 * HIG,
Expand Down
9 changes: 2 additions & 7 deletions qiskit/visualization/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -890,11 +890,6 @@ def draw_wires(self, wires):

return lines

@staticmethod
def label_for_conditional(node):
"""Creates the label for a conditional instruction."""
return "= %s" % node.op.condition[1]

@staticmethod
def special_label(node):
"""Some instructions have special labels"""
Expand Down Expand Up @@ -1384,7 +1379,7 @@ def set_cl_multibox(self, creg, val, top_connect="┴"):
label = f"{bit_reg.name}_{bit_index} {label_bool}"
self.set_clbit(creg, BoxOnClWire(label=label, top_connect=top_connect))
else:
label = "= %s" % val
label = "%s" % str(hex(val))
self.set_clbit(creg[0], BoxOnClWire(label=label, top_connect=top_connect))
else:
if isinstance(creg, Clbit):
Expand All @@ -1410,7 +1405,7 @@ def set_cond_bullets(self, val, clbits):
for i, bit in enumerate(clbits):
bot_connect = " "
if bit == clbits[-1]:
bot_connect = "=%s" % str(int(val, 2))
bot_connect = "%s" % str(hex(int(val, 2)))
if vlist[i] == "1":
self.set_clbit(bit, ClBullet(top_connect="║", bot_connect=bot_connect))
elif vlist[i] == "0":
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
fixes:
- |
Fixed an issue with the :func:`~qiskit.visualization.circuit_drawer`
function and :meth:`~qiskit.circuit.QuantumCircuit.draw` method of
:class:`~qiskit.circuit.QuantumCircuit`. When displaying a ``measure``
instruction containing a classical ``condition`` using the ``mpl`` or
``latex`` options, the ``condition`` information would sometimes
overwrite the ``measure`` display.
fixes:
- |
Fixed an issue with the :func:`~qiskit.visualization.circuit_drawer`
function and :meth:`~qiskit.circuit.QuantumCircuit.draw` method of
:class:`~qiskit.circuit.QuantumCircuit`. The ``mpl`` drawer used hex
notation to display the ``condition`` value, whereas the ``text`` and
``latex`` drawers used decimal notation. Now all three drawers use
hex notation.
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.
Binary file modified test/ipynb/mpl/circuit/references/user_ax.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 16 additions & 1 deletion test/ipynb/mpl/circuit/test_circuit_matplotlib_drawer.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,9 @@ def test_user_ax_subplot(self):

fig = plt.figure(1, figsize=(6, 4))
fig.patch.set_facecolor("white")
fig.add_subplot(1, 2, 1)
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
ax1.plot([1, 2, 3])

circuit = QuantumCircuit(4)
circuit.h(0)
Expand All @@ -646,6 +647,20 @@ def test_figwidth(self):
circuit.x(2)
self.circuit_drawer(circuit, style={"figwidth": 5}, filename="figwidth.png")

def test_measures_with_conditions(self):
"""Test that a measure containing a condition displays"""
qr = QuantumRegister(2, "qr")
cr1 = ClassicalRegister(2, "cr1")
cr2 = ClassicalRegister(2, "cr2")
circuit = QuantumCircuit(qr, cr1, cr2)
circuit.h(0)
circuit.h(1)
circuit.measure(0, cr1[1])
circuit.measure(1, cr2[0]).c_if(cr1, 1)
circuit.h(0).c_if(cr2, 3)
self.circuit_drawer(circuit, cregbundle=False, filename="measure_cond_false.png")
self.circuit_drawer(circuit, cregbundle=True, filename="measure_cond_true.png")


if __name__ == "__main__":
unittest.main(verbosity=1)
2 changes: 1 addition & 1 deletion test/python/visualization/references/test_latex_4597.tex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
\nghost{ {q}_{0} : } & \lstick{ {q}_{0} : } & \qw & \qw & \qw & \qw\\
\nghost{ {q}_{1} : } & \lstick{ {q}_{1} : } & \qw & \qw & \qw & \qw\\
\nghost{ {q}_{2} : } & \lstick{ {q}_{2} : } & \qw & \gate{\mathrm{X}} & \qw & \qw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{3}}} \cw & \dstick{_{_{=2}}} \cw \cwx[-1] & \cw & \cw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{3}}} \cw & \control \cw^(0.0){^{\mathtt{0x2}}} \cwx[-1] & \cw & \cw\\
\\ }}
\end{document}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
\Qcircuit @C=1.0em @R=0.2em @!R { \\
\nghost{ {q}_{0} : } & \lstick{ {q}_{0} : } & \gate{\mathrm{H}} & \meter & \qw & \gate{\mathrm{H}} & \qw & \qw\\
\nghost{ {q}_{1} : } & \lstick{ {q}_{1} : } & \gate{\mathrm{H}} & \qw & \meter & \qw & \qw & \qw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{2}}} \cw & \dstick{_{_{0}}} \cw \cwx[-2] & \dstick{_{_{1}}} \cw \cwx[-1] & \dstick{_{_{=2}}} \cw \cwx[-2] & \cw & \cw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{2}}} \cw & \dstick{_{_{\hspace{0.0em}0}}} \cw \ar @{<=} [-2,0] & \dstick{_{_{\hspace{0.0em}1}}} \cw \ar @{<=} [-1,0] & \control \cw^(0.0){^{\mathtt{0x2}}} \cwx[-2] & \cw & \cw\\
\\ }}
\end{document}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
\documentclass[border=2px]{standalone}

\usepackage[braket, qm]{qcircuit}
\usepackage{graphicx}

\begin{document}
\scalebox{1.0}{
\Qcircuit @C=1.0em @R=0.2em @!R { \\
\nghost{ {qr}_{0} : } & \lstick{ {qr}_{0} : } & \gate{\mathrm{H}} & \meter & \qw & \gate{\mathrm{H}} & \qw & \qw\\
\nghost{ {qr}_{1} : } & \lstick{ {qr}_{1} : } & \gate{\mathrm{H}} & \qw & \meter & \qw & \qw & \qw\\
\nghost{cr1_{0}:} & \lstick{cr1_{0}:} & \cw & \cw & \control \cw \cwx[-1] & \cw & \cw & \cw\\
\nghost{cr1_{1}:} & \lstick{cr1_{1}:} & \cw & \cw \ar @{<=} [-3,0] & \controlo \cw^(-0.3){^{\mathtt{0x1}}} \cwx[-1] & \cw & \cw & \cw\\
\nghost{cr2_{0}:} & \lstick{cr2_{0}:} & \cw & \cw & \cw \ar @{<=} [-3,0] & \control \cw \cwx[-4] & \cw & \cw\\
\nghost{cr2_{1}:} & \lstick{cr2_{1}:} & \cw & \cw & \cw & \control \cw^(0.0){^{\mathtt{0x3}}} \cwx[-1] & \cw & \cw\\
\\ }}
\end{document}
14 changes: 14 additions & 0 deletions test/python/visualization/references/test_latex_meas_cond_true.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
\documentclass[border=2px]{standalone}

\usepackage[braket, qm]{qcircuit}
\usepackage{graphicx}

\begin{document}
\scalebox{1.0}{
\Qcircuit @C=1.0em @R=0.2em @!R { \\
\nghost{ {qr}_{0} : } & \lstick{ {qr}_{0} : } & \gate{\mathrm{H}} & \meter & \qw & \gate{\mathrm{H}} & \qw & \qw\\
\nghost{ {qr}_{1} : } & \lstick{ {qr}_{1} : } & \gate{\mathrm{H}} & \qw & \meter & \qw & \qw & \qw\\
\nghost{cr1:} & \lstick{cr1:} & \lstick{/_{_{2}}} \cw & \dstick{_{_{\hspace{0.0em}1}}} \cw \ar @{<=} [-2,0] & \control \cw^(-0.3){^{\mathtt{0x1}}} \cwx[-1] & \cw & \cw & \cw\\
\nghost{cr2:} & \lstick{cr2:} & \lstick{/_{_{2}}} \cw & \cw & \dstick{_{_{\hspace{1.5em}0}}} \cw \ar @{<=} [-2,0] & \control \cw^(0.0){^{\mathtt{0x3}}} \cwx[-3] & \cw & \cw\\
\\ }}
\end{document}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
\Qcircuit @C=1.0em @R=0.2em @!R { \\
\nghost{ {qr}_{0} : } & \lstick{ {qr}_{0} : } & \gate{\mathrm{H}} & \meter & \qw & \qw & \qw\\
\nghost{ {qr}_{1} : } & \lstick{ {qr}_{1} : } & \qw & \qw & \gate{\mathrm{H}} & \qw & \qw\\
\nghost{cr:} & \lstick{cr:} & \lstick{/_{_{2}}} \cw & \dstick{_{_{0}}} \cw \cwx[-2] & \dstick{_{_{=1}}} \cw \cwx[-1] & \cw & \cw\\
\nghost{cr:} & \lstick{cr:} & \lstick{/_{_{2}}} \cw & \dstick{_{_{\hspace{0.0em}0}}} \cw \ar @{<=} [-2,0] & \control \cw^(0.0){^{\mathtt{0x1}}} \cwx[-1] & \cw & \cw\\
\\ }}
\end{document}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
\nghost{ {q}_{0} : } & \lstick{ {q}_{0} : } & \gate{\mathrm{U}\,(\mathrm{0.3,0.2,0.1})} & \qw \barrier[0em]{2} & \qw & \ctrl{1} & \gate{\mathrm{H}} & \meter & \qw & \qw & \qw & \qw & \qw\\
\nghost{ {q}_{1} : } & \lstick{ {q}_{1} : } & \gate{\mathrm{H}} & \ctrl{1} & \qw & \targ & \meter & \qw & \qw & \qw & \qw & \qw & \qw\\
\nghost{ {q}_{2} : } & \lstick{ {q}_{2} : } & \qw & \targ & \qw & \qw & \qw & \qw & \gate{\mathrm{Z}} & \gate{\mathrm{X}} & \meter & \qw & \qw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{3}}} \cw & \cw & \cw & \cw & \dstick{_{_{1}}} \cw \cwx[-2] & \dstick{_{_{0}}} \cw \cwx[-3] & \dstick{_{_{=1}}} \cw \cwx[-1] & \dstick{_{_{=2}}} \cw \cwx[-1] & \dstick{_{_{2}}} \cw \cwx[-1] & \cw & \cw\\
\nghost{c:} & \lstick{c:} & \lstick{/_{_{3}}} \cw & \cw & \cw & \cw & \dstick{_{_{\hspace{0.0em}1}}} \cw \ar @{<=} [-2,0] & \dstick{_{_{\hspace{0.0em}0}}} \cw \ar @{<=} [-3,0] & \control \cw^(0.0){^{\mathtt{0x1}}} \cwx[-1] & \control \cw^(0.0){^{\mathtt{0x2}}} \cwx[-1] & \dstick{_{_{\hspace{0.0em}2}}} \cw \ar @{<=} [-1,0] & \cw & \cw\\
\\ }}
\end{document}
18 changes: 18 additions & 0 deletions test/python/visualization/test_circuit_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,24 @@ def test_inst_with_cbits(self):

self.assertEqualToReference(filename)

def test_measures_with_conditions(self):
"""Test that a measure containing a condition displays"""
filename1 = self._get_resource_path("test_latex_meas_cond_false.tex")
filename2 = self._get_resource_path("test_latex_meas_cond_true.tex")
qr = QuantumRegister(2, "qr")
cr1 = ClassicalRegister(2, "cr1")
cr2 = ClassicalRegister(2, "cr2")
circuit = QuantumCircuit(qr, cr1, cr2)
circuit.h(0)
circuit.h(1)
circuit.measure(0, cr1[1])
circuit.measure(1, cr2[0]).c_if(cr1, 1)
circuit.h(0).c_if(cr2, 3)
circuit_drawer(circuit, cregbundle=False, filename=filename1, output="latex_source")
circuit_drawer(circuit, cregbundle=True, filename=filename2, output="latex_source")
self.assertEqualToReference(filename1)
self.assertEqualToReference(filename2)


if __name__ == "__main__":
unittest.main(verbosity=2)
Loading

0 comments on commit 0271b7f

Please sign in to comment.