Skip to content

Commit 2ec8f8f

Browse files
1ucian0Cryorisjakelishman
authored
The parameter idle_wires default flipped to False in all circuit drawers (Qiskit#13865)
* The parameter ``idle_wires`` default flipped to False in all circuit drawers * reno * readjust tests * test.python.visualization.test_circuit_text_drawer * adjust visual tests * bug in the tests * adjust test * black * testing * adjust tests * revert test changes * new reno * fix layout-related plots there's some bloch sphere plot failure which likely shouldn't be related to this, let's see if it persists * top-level handling of "auto" handle "auto" at the circuit_drawer level and subsequently use on booleans in internal logic * Fix idle_wires None case Co-authored-by: Jake Lishman <[email protected]> --------- Co-authored-by: Julien Gacon <[email protected]> Co-authored-by: Julien Gacon <[email protected]> Co-authored-by: Jake Lishman <[email protected]>
1 parent 519ce51 commit 2ec8f8f

File tree

12 files changed

+166
-23
lines changed

12 files changed

+166
-23
lines changed

qiskit/circuit/quantumcircuit.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3421,7 +3421,7 @@ def draw(
34213421
reverse_bits: bool | None = None,
34223422
justify: str | None = None,
34233423
vertical_compression: str | None = "medium",
3424-
idle_wires: bool | None = None,
3424+
idle_wires: bool | str | None = None,
34253425
with_layout: bool = True,
34263426
fold: int | None = None,
34273427
# The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be
@@ -3497,8 +3497,10 @@ def draw(
34973497
merges the lines generated by the `text` output so the drawing
34983498
will take less vertical room. Default is ``medium``. Only used by
34993499
the ``text`` output, will be silently ignored otherwise.
3500-
idle_wires: Include idle wires (wires with no circuit elements)
3501-
in output visualization. Default is ``True`` unless the
3500+
idle_wires: Include (or not) idle wires (wires with no circuit elements)
3501+
in output visualization. The string ``"auto"`` is also possible, in which
3502+
case idle wires are show except that the circuit has a layout attached.
3503+
Default is ``"auto"`` unless the
35023504
user config file (usually ``~/.qiskit/settings.conf``) has an
35033505
alternative value set. For example, ``circuit_idle_wires = False``.
35043506
with_layout: Include layout information, with labels on the

qiskit/visualization/circuit/_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,9 @@ def _get_layered_instructions(
450450
else:
451451
nodes = _LayerSpooler(dag, qubits, clbits, justify, measure_map)
452452

453-
# Optionally remove all idle wires and instructions that are on them and
454-
# on them only.
455453
if not idle_wires:
454+
# Optionally remove all idle wires and instructions that are on them and
455+
# on them only.
456456
for wire in dag.idle_wires(ignore=["barrier", "delay"]):
457457
if wire in qubits:
458458
qubits.remove(wire)

qiskit/visualization/circuit/circuit_visualization.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def circuit_drawer(
6464
reverse_bits: bool | None = None,
6565
justify: str | None = None,
6666
vertical_compression: str | None = "medium",
67-
idle_wires: bool | None = None,
67+
idle_wires: bool | str | None = None,
6868
with_layout: bool = True,
6969
fold: int | None = None,
7070
# The type of ax is matplotlib.axes.Axes, but this is not a fixed dependency, so cannot be
@@ -141,8 +141,10 @@ def circuit_drawer(
141141
merges the lines generated by the `text` output so the drawing
142142
will take less vertical room. Default is ``medium``. Only used by
143143
the ``text`` output, will be silently ignored otherwise.
144-
idle_wires: Include idle wires (wires with no circuit elements)
145-
in output visualization. Default is ``True`` unless the
144+
idle_wires: Include (or not) idle wires (wires with no circuit elements)
145+
in output visualization. The string ``"auto"`` is also possible, in which
146+
case idle wires are show except that the circuit has a layout attached.
147+
Default is ``"auto"`` unless the
146148
user config file (usually ``~/.qiskit/settings.conf``) has an
147149
alternative value set. For example, ``circuit_idle_wires = False``.
148150
with_layout: Include layout information, with labels on the
@@ -205,7 +207,7 @@ def circuit_drawer(
205207
# Get default from config file else use text
206208
default_output = "text"
207209
default_reverse_bits = False
208-
default_idle_wires = config.get("circuit_idle_wires", True)
210+
default_idle_wires = config.get("circuit_idle_wires", "auto")
209211
if config:
210212
default_output = config.get("circuit_drawer", "text")
211213
if default_output == "auto":
@@ -223,6 +225,11 @@ def circuit_drawer(
223225

224226
if idle_wires is None:
225227
idle_wires = default_idle_wires
228+
if isinstance(idle_wires, str):
229+
if idle_wires == "auto":
230+
idle_wires = hasattr(circuit, "_layout") and circuit._layout is None
231+
else:
232+
raise VisualizationError(f"Parameter idle_wires={idle_wires} unrecognized.")
226233

227234
if wire_order is not None and reverse_bits:
228235
raise VisualizationError(
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
upgrade_visualization:
3+
- |
4+
The ``idle_wires`` parameter in all circuit drawers has been extended with a new option, ``"auto"``, which is now
5+
the default behavior. If you still want to display wires without instructions, explicitly set ``idle_wires=True``.
6+
7+
When set to ``"auto"``, the behavior is as follows:
8+
- If the circuit has a defined ``.layout`` attribute, ``idle_wires`` is automatically set to ``False`` (hiding idle wires).
9+
- Otherwise, ``idle_wires`` remains ``True`` (showing all wires, as previous default).
10+
11+
Here an example. A circuit without a layout, using ``idle_wires="auto"``:
12+
13+
.. code-block:: text
14+
15+
qr_0: ────────
16+
┌───┐┌─┐
17+
qr_1: ┤ H ├┤M├
18+
└───┘└╥┘
19+
cr_0: ══════╬═
20+
21+
cr_1: ══════╩═
22+
23+
Once a layout is applied, ``idle_wires="auto"`` sets ``idle_wires`` to ``False``, hiding idle wires:
24+
25+
.. code-block:: text
26+
27+
┌───┐┌─┐
28+
qr_1 -> 1 ┤ H ├┤M├
29+
└───┘└╥┘
30+
cr_1: ══════╩═
31+
32+
If you want to display all wires in a laid-out circuit, set ``idle_wires=True`` explicitly:
33+
34+
.. code-block:: text
35+
36+
qr_0 -> 0 ────────
37+
┌───┐┌─┐
38+
qr_1 -> 1 ┤ H ├┤M├
39+
└───┘└╥┘
40+
ancilla_0 -> 2 ──────╫─
41+
42+
cr_0: ══════╬═
43+
44+
cr_1: ══════╩═
45+
46+
As quantum computers scale to more qubits, even small circuits can produce large circuit representations after
47+
transpilation. The ``"auto"`` setting helps improve readability by hiding unnecessary wires when possible.

test/python/visualization/test_circuit_latex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def test_partial_layout(self):
441441
seed_transpiler=0,
442442
)
443443

444-
circuit_drawer(transpiled, filename=filename, output="latex_source")
444+
circuit_drawer(transpiled, filename=filename, output="latex_source", idle_wires=True)
445445

446446
self.assertEqualToReference(filename)
447447

test/python/visualization/test_circuit_text_drawer.py

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3237,7 +3237,7 @@ class TestTextWithLayout(QiskitTestCase):
32373237
"""The with_layout option"""
32383238

32393239
def test_with_no_layout(self):
3240-
"""A circuit without layout"""
3240+
"""A circuit without layout and idle_wires=auto"""
32413241
expected = "\n".join(
32423242
[
32433243
" ",
@@ -3252,10 +3252,13 @@ def test_with_no_layout(self):
32523252
qr = QuantumRegister(3, "q")
32533253
circuit = QuantumCircuit(qr)
32543254
circuit.h(qr[1])
3255-
self.assertEqual(str(circuit_drawer(circuit, output="text", initial_state=True)), expected)
3255+
self.assertEqual(
3256+
str(circuit_drawer(circuit, output="text", initial_state=True, idle_wires="auto")),
3257+
expected,
3258+
)
32563259

3257-
def test_mixed_layout(self):
3258-
"""With a mixed layout."""
3260+
def test_mixed_layout_idle_wires_true(self):
3261+
"""With a mixed layout and idle_wires=True"""
32593262
expected = "\n".join(
32603263
[
32613264
" ┌───┐",
@@ -3279,11 +3282,45 @@ def test_mixed_layout(self):
32793282
circuit_with_layout = pass_(circuit, property_set={"layout": layout})
32803283

32813284
self.assertEqual(
3282-
str(circuit_drawer(circuit_with_layout, output="text", initial_state=True)), expected
3285+
str(
3286+
circuit_drawer(
3287+
circuit_with_layout, output="text", initial_state=True, idle_wires=True
3288+
)
3289+
),
3290+
expected,
32833291
)
32843292

3285-
def test_partial_layout(self):
3286-
"""With a partial layout.
3293+
def test_mixed_layout_idle_wires_auto(self):
3294+
"""With a mixed layout and idle_wires=False"""
3295+
expected = "\n".join(
3296+
[
3297+
" ┌───┐",
3298+
"v_0 -> 0 |0>┤ H ├",
3299+
" ├───┤",
3300+
"v_1 -> 3 |0>┤ H ├",
3301+
" └───┘",
3302+
]
3303+
)
3304+
qr = QuantumRegister(2, "v")
3305+
ancilla = QuantumRegister(2, "ancilla")
3306+
circuit = QuantumCircuit(qr, ancilla)
3307+
circuit.h(qr)
3308+
3309+
pass_ = ApplyLayout()
3310+
pass_.property_set["layout"] = Layout({qr[0]: 0, ancilla[1]: 1, ancilla[0]: 2, qr[1]: 3})
3311+
circuit_with_layout = pass_(circuit)
3312+
3313+
self.assertEqual(
3314+
str(
3315+
circuit_drawer(
3316+
circuit_with_layout, output="text", initial_state=True, idle_wires="auto"
3317+
)
3318+
),
3319+
expected,
3320+
)
3321+
3322+
def test_partial_layout_idle_true(self):
3323+
"""With a partial layout and idle_wires=True.
32873324
See: https://github.com/Qiskit/qiskit-terra/issues/4757"""
32883325
expected = "\n".join(
32893326
[
@@ -3309,7 +3346,38 @@ def test_partial_layout(self):
33093346
)
33103347
circuit._layout.initial_layout.add_register(qr)
33113348

3312-
self.assertEqual(str(circuit_drawer(circuit, output="text", initial_state=True)), expected)
3349+
self.assertEqual(
3350+
str(circuit_drawer(circuit, output="text", initial_state=True, idle_wires=True)),
3351+
expected,
3352+
)
3353+
3354+
def test_partial_layout_idle_auto(self):
3355+
"""With a partial layout and idle_wires="auto"
3356+
See: https://github.com/Qiskit/qiskit-terra/issues/4757"""
3357+
expected = "\n".join(
3358+
[
3359+
" ┌───┐",
3360+
"v_0 -> 0 |0>┤ H ├",
3361+
" ├───┤",
3362+
"v_1 -> 3 |0>┤ H ├",
3363+
" └───┘",
3364+
]
3365+
)
3366+
qr = QuantumRegister(2, "v")
3367+
pqr = QuantumRegister(4, "physical")
3368+
circuit = QuantumCircuit(pqr)
3369+
circuit.h(0)
3370+
circuit.h(3)
3371+
circuit._layout = TranspileLayout(
3372+
Layout({0: qr[0], 1: None, 2: None, 3: qr[1]}),
3373+
{qubit: index for index, qubit in enumerate(circuit.qubits)},
3374+
)
3375+
circuit._layout.initial_layout.add_register(qr)
3376+
3377+
self.assertEqual(
3378+
str(circuit_drawer(circuit, output="text", initial_state=True, idle_wires="auto")),
3379+
expected,
3380+
)
33133381

33143382
def test_with_classical_regs(self):
33153383
"""Involving classical registers"""
@@ -3341,7 +3409,12 @@ def test_with_classical_regs(self):
33413409
circuit_with_layout = pass_(circuit, property_set={"layout": layout})
33423410

33433411
self.assertEqual(
3344-
str(circuit_drawer(circuit_with_layout, output="text", initial_state=True)), expected
3412+
str(
3413+
circuit_drawer(
3414+
circuit_with_layout, output="text", initial_state=True, idle_wires=True
3415+
)
3416+
),
3417+
expected,
33453418
)
33463419

33473420
def test_with_layout_but_disable(self):
@@ -3370,7 +3443,11 @@ def test_with_layout_but_disable(self):
33703443
circuit.measure(pqr[2], cr[0])
33713444
circuit.measure(pqr[3], cr[1])
33723445
self.assertEqual(
3373-
str(circuit_drawer(circuit, output="text", initial_state=True, with_layout=False)),
3446+
str(
3447+
circuit_drawer(
3448+
circuit, output="text", initial_state=True, with_layout=False, idle_wires=True
3449+
)
3450+
),
33743451
expected,
33753452
)
33763453

@@ -3448,7 +3525,10 @@ def test_after_transpile(self):
34483525
optimization_level=0,
34493526
seed_transpiler=0,
34503527
)
3451-
self.assertEqual(qc_result.draw(output="text", cregbundle=False).single_string(), expected)
3528+
self.assertEqual(
3529+
qc_result.draw(output="text", cregbundle=False, idle_wires=True).single_string(),
3530+
expected,
3531+
)
34523532

34533533

34543534
class TestTextInitialValue(QiskitTestCase):
@@ -4145,7 +4225,12 @@ def test_inner_wire_map_control_op(self):
41454225
self.assertEqual(
41464226
str(
41474227
circuit_drawer(
4148-
circuit, output="text", fold=78, initial_state=False, cregbundle=False
4228+
circuit,
4229+
output="text",
4230+
fold=78,
4231+
initial_state=False,
4232+
cregbundle=False,
4233+
idle_wires=True,
41494234
)
41504235
),
41514236
expected,
-11.6 KB
Loading
-14.9 KB
Loading
-15.5 KB
Loading
-13.4 KB
Loading

0 commit comments

Comments
 (0)