From 73a617a4d8ee853cc08528a98f42a21be0ed0ab1 Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Sat, 9 Nov 2024 02:32:29 +0900 Subject: [PATCH] Adding new feature wire_options to draw_mpl function (#6486) **Context:** On the level of mid-scale algorithms, it might be nice to differentiate between different "types" of wires, for example by coloring them differently, or giving them distinct line styles. As an example, in https://github.com/PennyLaneAI/qml/pull/1185 on preparing matrix product states, there are auxiliary bond qubits and physical qubits, and coloring them differently would be a neat thing to do. **Description of the Change:** Update the output wire_options that could change the line style and color for circuit output. ```python @qml.qnode(qml.device("default.qubit")) def node(x): for w in range(5): qml.Hadamard(w) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) # Make all wires cyan and bold, # except for wires 2 and 6, which are dashed and another color wire_options = {"color": "cyan", "linewidth": 5, 2: {"linestyle": "--", "color": "red"}, 6: {"linestyle": "--", "color": "orange"} } _,ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) ``` **Benefits:** When complicated sates and quantum circuits diagram are created, wires could be marked with different selections. **Possible Drawbacks:** N/A **Related GitHub Issues:** https://github.com/PennyLaneAI/pennylane/issues/6165 --------- Co-authored-by: David Wierichs Co-authored-by: ringo-but-quantum <> Co-authored-by: Astral Cai Co-authored-by: Christina Lee --- doc/_static/draw_mpl/per_wire_options.png | Bin 0 -> 37428 bytes doc/_static/tape_mpl/per_wire_options.png | Bin 0 -> 22864 bytes doc/code/qml_drawer.rst | 2 +- doc/releases/changelog-dev.md | 5 ++ pennylane/drawer/draw.py | 30 ++++++++-- pennylane/drawer/mpldrawer.py | 24 ++++++-- pennylane/drawer/tape_mpl.py | 36 ++++++++--- tests/drawer/test_draw_mpl.py | 69 ++++++++++++++++++++++ 8 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 doc/_static/draw_mpl/per_wire_options.png create mode 100644 doc/_static/tape_mpl/per_wire_options.png diff --git a/doc/_static/draw_mpl/per_wire_options.png b/doc/_static/draw_mpl/per_wire_options.png new file mode 100644 index 0000000000000000000000000000000000000000..d4baf342c975956116d7deab586405e7d51860e6 GIT binary patch literal 37428 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
  • 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

    9Xv=9`1;f(M6(u&+7?{r!D3lNQL# z%#=k!#DdQq4=@ZDc7N=L`E3zN9`5u&Rmu#G;0AYsw zXHSHlRM*ySz@u6gp}2fmXqndX&b{vLE4jJ3W3sYVV7(W_K&X25Z24y=T#%~z`nJab zBkUqlRlTdbd%dQnCi*rl{`&CkE+eT+r-0QKnc)d8bH z;<)|1rI@0Ucjqhv9a$6O<=T1>xc3}d6cD5`IKrvVy63qfMOx3mpai6u z1rz~Qm6b9!&lhWqK3IGhDqk@ZspIK%b#uE9{as8^kxKu-zz?r>u7wx|q)7409GBSJ zw-sz`ZTFzr#l=T^C%vk_H41=i%29mKO9SYoI(yVI3)r9QBg8JqRYyBU&Z72fK&Hmt n!hSZHtE1()?tjwTM!0NcIL-w*tP{cMFdFN(s;8_q`{n-uNz|;O literal 0 HcmV?d00001 diff --git a/doc/_static/tape_mpl/per_wire_options.png b/doc/_static/tape_mpl/per_wire_options.png new file mode 100644 index 0000000000000000000000000000000000000000..529ae1f2abae85dd7eafe4c19f569bf71ef1057b GIT binary patch literal 22864 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 RXD*pnnX?LK(j*OT{aImprovements 🛠 +* Added support for the `wire_options` dictionary to customize wire line formatting in `qml.draw_mpl` circuit + visualizations, allowing global and per-wire customization with options like `color`, `linestyle`, and `linewidth`. + [(#6486)](https://github.com/PennyLaneAI/pennylane/pull/6486) +

    Capturing and representing hybrid programs

    * `jax.vmap` can be captured with `qml.capture.make_plxpr` and is compatible with quantum circuits. @@ -54,6 +58,7 @@ This release contains contributions from (in alphabetical order): +Shiwen An Astral Cai, Pietropaolo Frisoni, Andrija Paurevic diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index df9e6e76829..2a3f1202560 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -385,7 +385,9 @@ def draw_mpl( fontsize (float or str): fontsize for text. Valid strings are ``{'xx-small', 'x-small', 'small', 'medium', large', 'x-large', 'xx-large'}``. Default is ``14``. - wire_options (dict): matplotlib formatting options for the wire lines + wire_options (dict): matplotlib formatting options for the wire lines. In addition to + standard options, options per wire can be specified with ``wire_label: options`` + pairs, also see examples below. label_options (dict): matplotlib formatting options for the wire labels show_wire_labels (bool): Whether or not to show the wire labels. active_wire_notches (bool): whether or not to add notches indicating active wires. @@ -458,7 +460,8 @@ def circuit2(x, y): **Wires:** - The keywords ``wire_order`` and ``show_all_wires`` control the location of wires from top to bottom. + The keywords ``wire_order`` and ``show_all_wires`` control the location of wires + from top to bottom. .. code-block:: python @@ -470,8 +473,8 @@ def circuit2(x, y): :width: 60% :target: javascript:void(0); - If a wire is in ``wire_order``, but not in the ``tape``, it will be omitted by default. Only by selecting - ``show_all_wires=True`` will empty wires be displayed. + If a wire is in ``wire_order``, but not in the ``tape``, it will be omitted by default. + Only by selecting ``show_all_wires=True`` will empty wires be displayed. .. code-block:: python @@ -568,6 +571,25 @@ def circuit2(x, y): :width: 60% :target: javascript:void(0); + + Additionally, ``wire_options`` may contain sub-dictionaries of matplotlib options assigned + to separate wire labels, which will control the line style for the respective individual wires. + + .. code-block:: python + + wire_options = { + 'color': 'teal', # all wires but wire 2 will be teal + 'linewidth': 5, # all wires but wire 2 will be bold + 2: {'color': 'orange', 'linestyle': '--'}, # wire 2 will be orange and dashed + } + fig, ax = qml.draw_mpl(circuit, wire_options=wire_options)(1.2345,1.2345) + fig.show() + + .. figure:: ../../_static/draw_mpl/per_wire_options.png + :align: center + :width: 60% + :target: javascript:void(0); + **Levels:** The ``level`` keyword argument allows one to select a subset of the transforms to apply on the ``QNode`` diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index eada58dcad9..64e92a50cfe 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -294,11 +294,25 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None if wire_options is None: wire_options = {} - # adding wire lines - self._wire_lines = [ - plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, **wire_options) - for wire in range(self.n_wires) - ] + # Separate global options from per wire options + global_options = {k: v for k, v in wire_options.items() if not isinstance(v, dict)} + wire_specific_options = {k: v for k, v in wire_options.items() if isinstance(v, dict)} + + # Adding wire lines with individual styles based on wire_options + self._wire_lines = [] + for wire in range(self.n_wires): + specific_options = wire_specific_options.get(wire, {}) + line_options = {**global_options, **specific_options} + + # Create Line2D with the combined options + line = plt.Line2D( + (-1, self.n_layers), + (wire, wire), + zorder=1, + **line_options, + ) + self._wire_lines.append(line) + for line in self._wire_lines: self._ax.add_line(line) diff --git a/pennylane/drawer/tape_mpl.py b/pennylane/drawer/tape_mpl.py index 76c485cc67b..b1aa8f93af4 100644 --- a/pennylane/drawer/tape_mpl.py +++ b/pennylane/drawer/tape_mpl.py @@ -303,7 +303,9 @@ def tape_mpl( fontsize (float or str): fontsize for text. Valid strings are ``{'xx-small', 'x-small', 'small', 'medium', large', 'x-large', 'xx-large'}``. Default is ``14``. - wire_options (dict): matplotlib formatting options for the wire lines + wire_options (dict): matplotlib formatting options for the wire lines. In addition to + standard options, options per wire can be specified with ``wire_label: options`` + pairs, also see examples below. label_options (dict): matplotlib formatting options for the wire labels show_wire_labels (bool): Whether or not to show the wire labels. active_wire_notches (bool): whether or not to add notches indicating active wires. @@ -328,7 +330,7 @@ def tape_mpl( measurements = [qml.expval(qml.Z(0))] tape = qml.tape.QuantumTape(ops, measurements) - fig, ax = tape_mpl(tape) + fig, ax = qml.drawer.tape_mpl(tape) fig.show() .. figure:: ../../_static/tape_mpl/default.png @@ -350,7 +352,7 @@ def tape_mpl( measurements = [qml.expval(qml.Z(0))] tape2 = qml.tape.QuantumTape(ops, measurements) - fig, ax = tape_mpl(tape2, decimals=2) + fig, ax = qml.drawer.tape_mpl(tape2, decimals=2) .. figure:: ../../_static/tape_mpl/decimals.png :align: center @@ -363,7 +365,7 @@ def tape_mpl( .. code-block:: python - fig, ax = tape_mpl(tape, wire_order=[3,2,1,0]) + fig, ax = qml.drawer.tape_mpl(tape, wire_order=[3,2,1,0]) .. figure:: ../../_static/tape_mpl/wire_order.png :align: center @@ -375,7 +377,7 @@ def tape_mpl( .. code-block:: python - fig, ax = tape_mpl(tape, wire_order=["aux"], show_all_wires=True) + fig, ax = qml.drawer.tape_mpl(tape, wire_order=["aux"], show_all_wires=True) .. figure:: ../../_static/tape_mpl/show_all_wires.png :align: center @@ -389,7 +391,7 @@ def tape_mpl( .. code-block:: python - fig, ax = tape_mpl(tape) + fig, ax = qml.drawer.tape_mpl(tape) fig.suptitle("My Circuit", fontsize="xx-large") options = {'facecolor': "white", 'edgecolor': "#f57e7e", "linewidth": 6, "zorder": -1} @@ -413,7 +415,7 @@ def tape_mpl( .. code-block:: python - fig, ax = tape_mpl(tape, style='sketch') + fig, ax = qml.drawer.tape_mpl(tape, style='sketch') .. figure:: ../../_static/tape_mpl/sketch_style.png :align: center @@ -437,7 +439,7 @@ def tape_mpl( plt.rcParams['lines.linewidth'] = 5 plt.rcParams['figure.facecolor'] = 'ghostwhite' - fig, ax = tape_mpl(tape, style="rcParams") + fig, ax = qml.drawer.tape_mpl(tape, style="rcParams") .. figure:: ../../_static/tape_mpl/rcparams.png :align: center @@ -450,7 +452,7 @@ def tape_mpl( .. code-block:: python - fig, ax = tape_mpl(tape, wire_options={'color':'teal', 'linewidth': 5}, + fig, ax = qml.drawer.tape_mpl(tape, wire_options={'color':'teal', 'linewidth': 5}, label_options={'size': 20}) .. figure:: ../../_static/tape_mpl/wires_labels.png @@ -458,6 +460,22 @@ def tape_mpl( :width: 60% :target: javascript:void(0); + Additionally, ``wire_options`` may contain sub-dictionaries of matplotlib options assigned + to separate wire labels, which will control the line style for the respective individual wires. + + .. code-block:: python + + wire_options = { + 'color': 'teal', # all wires but wire 2 will be teal + 'linewidth': 5, # all wires but wire 2 will be bold + 2: {'color': 'orange', 'linestyle': '--'}, # wire 2 will be orange and dashed + } + fig, ax = qml.drawer.tape_mpl(tape, wire_options=wire_options) + + .. figure:: ../../_static/tape_mpl/per_wire_options.png + :align: center + :width: 60% + :target: javascript:void(0); """ restore_params = {} diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index f2e7173298b..23ca78d19a2 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -328,6 +328,75 @@ def test_wire_options(self): assert w.get_color() == "black" assert w.get_linewidth() == 4 + @qml.qnode(dev) + def f_circ(x): + """Circuit on ten qubits.""" + qml.RX(x, wires=0) + for w in range(10): + qml.Hadamard(w) + return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) + + # All wires are orange + wire_options = {"color": "orange"} + _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) + + for w in ax.lines: + assert w.get_color() == "orange" + + # Wires are orange and cyan + wire_options = {0: {"color": "orange"}, 1: {"color": "cyan"}} + _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) + + assert ax.lines[0].get_color() == "orange" + assert ax.lines[1].get_color() == "cyan" + assert ax.lines[2].get_color() == "black" + + # Make all wires cyan and bold, + # except for wires 2 and 6, which are dashed and another color + wire_options = { + "color": "cyan", + "linewidth": 5, + 2: {"linestyle": "--", "color": "red"}, + 6: {"linestyle": "--", "color": "orange", "linewidth": 1}, + } + _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) + + for i, w in enumerate(ax.lines): + if i == 2: + assert w.get_color() == "red" + assert w.get_linestyle() == "--" + assert w.get_linewidth() == 5 + elif i == 6: + assert w.get_color() == "orange" + assert w.get_linestyle() == "--" + assert w.get_linewidth() == 1 + else: + assert w.get_color() == "cyan" + assert w.get_linestyle() == "-" + assert w.get_linewidth() == 5 + + wire_options = { + "linewidth": 5, + 2: {"linestyle": "--", "color": "red"}, + 6: {"linestyle": "--", "color": "orange"}, + } + + _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) + + for i, w in enumerate(ax.lines): + if i == 2: + assert w.get_color() == "red" + assert w.get_linestyle() == "--" + assert w.get_linewidth() == 5 + elif i == 6: + assert w.get_color() == "orange" + assert w.get_linestyle() == "--" + assert w.get_linewidth() == 5 + else: + assert w.get_color() == "black" + assert w.get_linestyle() == "-" + assert w.get_linewidth() == 5 + plt.close()