Skip to content

Commit 44f794a

Browse files
authored
Fix display of sidetext gates with conditions (Qiskit#7673)
* First testing * Fix display of sidetext gates with conditions in text * Add comment * Start it up again * Add mpl and latex tests * Add cu1 and rzz tests * Start it up again * Break out RZZ and CU1 * Restart
1 parent 5b53a15 commit 44f794a

File tree

7 files changed

+123
-1
lines changed

7 files changed

+123
-1
lines changed

qiskit/visualization/text.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ class Bullet(DirectOnQuWire):
430430

431431
def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
432432
super().__init__("■")
433+
self.conditional = conditional
433434
self.top_connect = top_connect
434435
self.bot_connect = "║" if conditional else bot_connect
435436
if label and bottom:
@@ -451,6 +452,7 @@ class OpenBullet(DirectOnQuWire):
451452

452453
def __init__(self, top_connect="", bot_connect="", conditional=False, label=None, bottom=False):
453454
super().__init__("o")
455+
self.conditional = conditional
454456
self.top_connect = top_connect
455457
self.bot_connect = "║" if conditional else bot_connect
456458
if label and bottom:
@@ -1033,6 +1035,10 @@ def _set_ctrl_state(self, node, conditional, ctrl_text, bottom):
10331035
ctrl_qubits = node.qargs[:num_ctrl_qubits]
10341036
cstate = f"{op.ctrl_state:b}".rjust(num_ctrl_qubits, "0")[::-1]
10351037
for i in range(len(ctrl_qubits)):
1038+
# For sidetext gate alignment, need to set every Bullet with
1039+
# conditional on if there's a condition.
1040+
if op.condition is not None:
1041+
conditional = True
10361042
if cstate[i] == "1":
10371043
gates.append(Bullet(conditional=conditional, label=ctrl_text, bottom=bottom))
10381044
else:
@@ -1502,3 +1508,5 @@ def connect_with(self, wire_char):
15021508
if label:
15031509
for affected_bit in affected_bits:
15041510
affected_bit.right_fill = len(label) + len(affected_bit.mid)
1511+
if isinstance(affected_bit, (Bullet, OpenBullet)) and affected_bit.conditional:
1512+
affected_bit.left_fill = len(label) + len(affected_bit.mid)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes a problem in the ``text`` circuit drawer when gates that
5+
use side text, such as the ``CPhaseGate`` and ``RZZGate``, when
6+
displayed with conditions would not display properly.
9.1 KB
Loading

test/ipynb/mpl/circuit/test_circuit_matplotlib_drawer.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
ZGate,
3636
SGate,
3737
U1Gate,
38+
CPhaseGate,
3839
)
3940
from qiskit.circuit.library import MCXVChain
4041
from qiskit.extensions import HamiltonianGate
@@ -863,6 +864,14 @@ def test_conditions_with_bits_reverse(self):
863864
circuit, cregbundle=False, reverse_bits=True, filename="cond_bits_reverse.png"
864865
)
865866

867+
def test_sidetext_with_condition(self):
868+
"""Test that sidetext gates align properly with conditions"""
869+
qr = QuantumRegister(2, "q")
870+
cr = ClassicalRegister(2, "c")
871+
circuit = QuantumCircuit(qr, cr)
872+
circuit.append(CPhaseGate(pi / 2), [qr[0], qr[1]]).c_if(cr[1], 1)
873+
self.circuit_drawer(circuit, cregbundle=False, filename="sidetext_condition.png")
874+
866875
def test_fold_with_conditions(self):
867876
"""Test that gates with conditions draw correctly when folding"""
868877
qr = QuantumRegister(3)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
\documentclass[border=2px]{standalone}
2+
3+
\usepackage[braket, qm]{qcircuit}
4+
\usepackage{graphicx}
5+
6+
\begin{document}
7+
\scalebox{1.0}{
8+
\Qcircuit @C=1.0em @R=0.8em @!R { \\
9+
\nghost{{q}_{0} : } & \lstick{{q}_{0} : } & \ctrl{1} & \dstick{\hspace{2.0em}\mathrm{P}\,(\mathrm{\frac{\pi}{2}})} \qw & \qw & \qw & \qw & \qw\\
10+
\nghost{{q}_{1} : } & \lstick{{q}_{1} : } & \control \qw & \qw & \qw & \qw & \qw & \qw\\
11+
\nghost{{c}_{0} : } & \lstick{{c}_{0} : } & \cw & \cw & \cw & \cw & \cw & \cw\\
12+
\nghost{{c}_{1} : } & \lstick{{c}_{1} : } & \control \cw^(0.0){^{\mathtt{}}} \cwx[-2] & \cw & \cw & \cw & \cw & \cw\\
13+
\\ }}
14+
\end{document}

test/python/visualization/test_circuit_latex.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from qiskit.visualization import circuit_drawer
2323
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile
2424
from qiskit.test.mock import FakeTenerife
25-
from qiskit.circuit.library import XGate, MCXGate, RZZGate, SwapGate, DCXGate
25+
from qiskit.circuit.library import XGate, MCXGate, RZZGate, SwapGate, DCXGate, CPhaseGate
2626
from qiskit.extensions import HamiltonianGate
2727
from qiskit.circuit import Parameter, Qubit, Clbit
2828
from qiskit.circuit.library import IQP
@@ -645,6 +645,16 @@ def test_conditions_with_bits_reverse(self):
645645
)
646646
self.assertEqualToReference(filename)
647647

648+
def test_sidetext_with_condition(self):
649+
"""Test that sidetext gates align properly with a condition"""
650+
filename = self._get_resource_path("test_latex_sidetext_condition.tex")
651+
qr = QuantumRegister(2, "q")
652+
cr = ClassicalRegister(2, "c")
653+
circuit = QuantumCircuit(qr, cr)
654+
circuit.append(CPhaseGate(pi / 2), [qr[0], qr[1]]).c_if(cr[1], 1)
655+
circuit_drawer(circuit, cregbundle=False, filename=filename, output="latex_source")
656+
self.assertEqualToReference(filename)
657+
648658

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

test/python/visualization/test_circuit_text_drawer.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,81 @@ def test_text_cp(self):
635635
circuit.append(CPhaseGate(pi / 2), [qr[2], qr[0]])
636636
self.assertEqual(str(_text_circuit_drawer(circuit)), expected)
637637

638+
def test_text_cu1_condition(self):
639+
"""Test cu1 with condition"""
640+
expected = "\n".join(
641+
[
642+
" ",
643+
"q_0: ────────■────────",
644+
" │U1(π/2) ",
645+
"q_1: ────────■────────",
646+
" ║ ",
647+
"q_2: ────────╫────────",
648+
" ║ ",
649+
"c_0: ════════╬════════",
650+
" ║ ",
651+
"c_1: ════════■════════",
652+
" ",
653+
"c_2: ═════════════════",
654+
" ",
655+
]
656+
)
657+
qr = QuantumRegister(3, "q")
658+
cr = ClassicalRegister(3, "c")
659+
circuit = QuantumCircuit(qr, cr)
660+
circuit.append(CU1Gate(pi / 2), [qr[0], qr[1]]).c_if(cr[1], 1)
661+
self.assertEqual(str(_text_circuit_drawer(circuit, initial_state=False)), expected)
662+
663+
def test_text_rzz_condition(self):
664+
"""Test rzz with condition"""
665+
expected = "\n".join(
666+
[
667+
" ",
668+
"q_0: ────────■────────",
669+
" │ZZ(π/2) ",
670+
"q_1: ────────■────────",
671+
" ║ ",
672+
"q_2: ────────╫────────",
673+
" ║ ",
674+
"c_0: ════════╬════════",
675+
" ║ ",
676+
"c_1: ════════■════════",
677+
" ",
678+
"c_2: ═════════════════",
679+
" ",
680+
]
681+
)
682+
qr = QuantumRegister(3, "q")
683+
cr = ClassicalRegister(3, "c")
684+
circuit = QuantumCircuit(qr, cr)
685+
circuit.append(RZZGate(pi / 2), [qr[0], qr[1]]).c_if(cr[1], 1)
686+
self.assertEqual(str(_text_circuit_drawer(circuit, initial_state=False)), expected)
687+
688+
def test_text_cp_condition(self):
689+
"""Test cp with condition"""
690+
expected = "\n".join(
691+
[
692+
" ",
693+
"q_0: ───────■───────",
694+
" │P(π/2) ",
695+
"q_1: ───────■───────",
696+
" ║ ",
697+
"q_2: ───────╫───────",
698+
" ║ ",
699+
"c_0: ═══════╬═══════",
700+
" ║ ",
701+
"c_1: ═══════■═══════",
702+
" ",
703+
"c_2: ═══════════════",
704+
" ",
705+
]
706+
)
707+
qr = QuantumRegister(3, "q")
708+
cr = ClassicalRegister(3, "c")
709+
circuit = QuantumCircuit(qr, cr)
710+
circuit.append(CPhaseGate(pi / 2), [qr[0], qr[1]]).c_if(cr[1], 1)
711+
self.assertEqual(str(_text_circuit_drawer(circuit, initial_state=False)), expected)
712+
638713
def test_text_cu1_reverse_bits(self):
639714
"""cu1 drawing with reverse_bits"""
640715
expected = "\n".join(

0 commit comments

Comments
 (0)