From 2cd5a3ed37b23b0f767c55f7c880194e533fcfd9 Mon Sep 17 00:00:00 2001 From: zazabap Date: Thu, 31 Oct 2024 00:59:47 +0900 Subject: [PATCH 01/39] Add TODO --- pennylane/drawer/draw.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index 5fa3cc57f4a..04f000b1c81 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -638,6 +638,7 @@ def circ(): """ + #TODO if catalyst_qjit(qnode): qnode = qnode.user_function From 5849c91895548ce65f0174ac0d6792e5e9ccfd7c Mon Sep 17 00:00:00 2001 From: zazabap Date: Thu, 31 Oct 2024 22:53:02 +0900 Subject: [PATCH 02/39] Update different color options --- pennylane/drawer/draw.py | 1 - pennylane/drawer/mpldrawer.py | 21 +++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index 04f000b1c81..5fa3cc57f4a 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -638,7 +638,6 @@ def circ(): """ - #TODO if catalyst_qjit(qnode): qnode = qnode.user_function diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index eada58dcad9..7d2f8797b91 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -295,10 +295,23 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=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) - ] + # self._wire_lines = [ + # plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, **wire_options) + # for wire in range(self.n_wires) + # ] + + default_color = "black" + + # Adding wire lines with individual colors based on wire_options + self._wire_lines = [] + for wire in range(self.n_wires): + # Get color for the current wire; use default if not specified + wire_color = wire_options.get(wire, {}).get("color", default_color) + + # Create Line2D with the specific color for this wire + line = plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, color=wire_color) + self._wire_lines.append(line) + for line in self._wire_lines: self._ax.add_line(line) From 1cff7065f5bb2dbcb7e946c4f6d4445c8fa23352 Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 14:16:19 +0900 Subject: [PATCH 03/39] Update wire options --- pennylane/drawer/mpldrawer.py | 36 +++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index 7d2f8797b91..2d5d12762f8 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -294,24 +294,32 @@ 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) - # ] - - default_color = "black" - - # Adding wire lines with individual colors based on wire_options + # Separate default options from specific wire options + default_options = {k: v for k, v in wire_options.items() if isinstance(k, str)} + wire_specific_options = {k: v for k, v in wire_options.items() if isinstance(k, int)} + + # Define defaults if "color" and "linewidth" aren't specified in default_options + default_color = default_options.get("color", "black") + default_linewidth = default_options.get("linewidth", 1) + + # Adding wire lines with individual styles based on wire_options self._wire_lines = [] for wire in range(self.n_wires): - # Get color for the current wire; use default if not specified - wire_color = wire_options.get(wire, {}).get("color", default_color) - - # Create Line2D with the specific color for this wire - line = plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, color=wire_color) + specific_options = wire_specific_options.get(wire, {}) + line_options = {**default_options, **specific_options} + + # Create Line2D with the combined options + line = plt.Line2D( + (-1, self.n_layers), + (wire, wire), + zorder=1, + color=line_options.get("color", default_color), + linewidth=line_options.get("linewidth", default_linewidth), + linestyle=line_options.get("linestyle", "-") + ) self._wire_lines.append(line) + for line in self._wire_lines: self._ax.add_line(line) From 432b8189a9145a070e94f02d3df436d359e35c7e Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 14:37:46 +0900 Subject: [PATCH 04/39] Update the test and format of mpldrawer.py --- tests/drawer/test_draw_mpl.py | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index f2e7173298b..79c573844c0 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -328,6 +328,43 @@ def test_wire_options(self): assert w.get_color() == "black" assert w.get_linewidth() == 4 + # Define the quantum function with @qml.qnode + @qml.qnode(dev) + def node(x): + qml.RX(x, wires=0) + qml.Hadamard(wires=1) + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) + + # Draw the circuit and save the plot + _, ax = qml.draw_mpl(node)(0.52) + + # All wires are orange + wire_options = {"color": "orange"} + _, ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) + + # Wires are orange and cyan + wire_options = { + 0: {"color": "orange"}, + 1: {"color": "cyan"} + } + _,ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) + + @qml.qnode(qml.device("default.qubit")) + def node(x): + for w in range(10): + 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) + plt.close() From b38e0cc4392e7dd3805c36ac6a3e48fee6333f67 Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 14:40:48 +0900 Subject: [PATCH 05/39] format update --- pennylane/drawer/mpldrawer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index 2d5d12762f8..87f281b839a 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -310,12 +310,12 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None # Create Line2D with the combined options line = plt.Line2D( - (-1, self.n_layers), - (wire, wire), - zorder=1, + (-1, self.n_layers), + (wire, wire), + zorder=1, color=line_options.get("color", default_color), linewidth=line_options.get("linewidth", default_linewidth), - linestyle=line_options.get("linestyle", "-") + linestyle=line_options.get("linestyle", "-") ) self._wire_lines.append(line) From 41d3348dc6dbe2df84329e88566ccb597ff43b16 Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 16:53:44 +0900 Subject: [PATCH 06/39] Update test function --- tests/drawer/test_draw_mpl.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 79c573844c0..a439daf59ca 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -330,28 +330,28 @@ def test_wire_options(self): # Define the quantum function with @qml.qnode @qml.qnode(dev) - def node(x): + def wire1(x): qml.RX(x, wires=0) qml.Hadamard(wires=1) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) # Draw the circuit and save the plot - _, ax = qml.draw_mpl(node)(0.52) + _, ax = qml.draw_mpl(wire1)(0.52) # All wires are orange wire_options = {"color": "orange"} - _, ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) + _, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) # Wires are orange and cyan wire_options = { 0: {"color": "orange"}, 1: {"color": "cyan"} } - _,ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) + _,ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) - @qml.qnode(qml.device("default.qubit")) - def node(x): + @qml.qnode(dev) + def wire1(x): for w in range(10): qml.Hadamard(w) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) @@ -363,7 +363,7 @@ def node(x): 2: {"linestyle": "--", "color": "red"}, 6: {"linestyle": "--", "color": "orange"} } - _,ax = qml.draw_mpl(node, wire_options=wire_options)(0.52) + _,ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) plt.close() From 9092bba3f99e9c4fd75d12502e5326c95271ac55 Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 17:06:10 +0900 Subject: [PATCH 07/39] add assertion and doc update --- doc/code/qml_drawer.rst | 48 +++++++++++++++++++++++++++++++++++ tests/drawer/test_draw_mpl.py | 20 ++++++++++++--- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/code/qml_drawer.rst b/doc/code/qml_drawer.rst index 69a03567910..3ed3fdafcdf 100644 --- a/doc/code/qml_drawer.rst +++ b/doc/code/qml_drawer.rst @@ -50,6 +50,54 @@ deleting the ``fontlist`` file in the Matplotlib cache directory) — to find th cache directory, run ``matplotlib.get_cachedir()``. If this font is not available, the drawer will fall back on a default font. +Wire Options +------------ + +The ``wire_options`` dictionary allows customization of the formatting for the wire lines in +the circuit visualization. This dictionary may contain standard matplotlib options +for line formatting, as well as entries with wire labels as keys and corresponding +dictionaries as values for specific wire line styling. For example, using keys such +as `color`, `linestyle`, and `linewidth` allows for per-wire customization. + +.. code-block:: python + + # Define the quantum function with @qml.qnode + @qml.qnode(dev) + def wire1(x): + qml.RX(x, wires=0) + qml.Hadamard(wires=1) + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) + + # Draw the circuit and save the plot + fig, ax = qml.draw_mpl(wire1)(0.52) + + # All wires are orange + wire_options = {"color": "orange"} + fig, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + + # Wires are orange and cyan + wire_options = { + 0: {"color": "orange"}, + 1: {"color": "cyan"} + } + fig, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + + @qml.qnode(dev) + def wire1(x): + for w in range(10): + 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"} + } + fig, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + Currently Available Styles ^^^^^^^^^^^^^^^^^^^^^^^^^^ .. |bws| image:: ../_static/style/black_white_style.png diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index a439daf59ca..d10812be39d 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -336,13 +336,13 @@ def wire1(x): qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) - # Draw the circuit and save the plot - _, ax = qml.draw_mpl(wire1)(0.52) - # All wires are orange wire_options = {"color": "orange"} _, ax = qml.draw_mpl(wire1, 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"}, @@ -350,6 +350,9 @@ def wire1(x): } _,ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + assert ax.lines[0].get_color() == "orange" + assert ax.lines[1].get_color() == "cyan" + @qml.qnode(dev) def wire1(x): for w in range(10): @@ -365,6 +368,17 @@ def wire1(x): } _,ax = qml.draw_mpl(wire1, 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() == "--" + elif i == 6: + assert w.get_color() == "orange" + assert w.get_linestyle() == "--" + else: + assert w.get_color() == "cyan" + assert w.get_linewidth() == 5 + plt.close() From c57e9a51a4e59606adceb78e8a4b64e1f6f2a398 Mon Sep 17 00:00:00 2001 From: zazabap Date: Fri, 1 Nov 2024 17:21:24 +0900 Subject: [PATCH 08/39] Update changelog-dev.md --- doc/releases/changelog-dev.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index df4ec5d605a..935704a78c7 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -6,6 +6,9 @@

Improvements 🛠

+* 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) +

Breaking changes 💔

Deprecations 👋

@@ -17,3 +20,5 @@

Contributors ✍️

This release contains contributions from (in alphabetical order): + +Shiwen An \ No newline at end of file From 5bb193d383528b8ae120e0ea737b1526cf70069e Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 14:18:55 +0900 Subject: [PATCH 09/39] reformated --- pennylane/drawer/mpldrawer.py | 3 +-- tests/drawer/test_draw_mpl.py | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index 87f281b839a..b7f801520d8 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -315,11 +315,10 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None zorder=1, color=line_options.get("color", default_color), linewidth=line_options.get("linewidth", default_linewidth), - linestyle=line_options.get("linestyle", "-") + linestyle=line_options.get("linestyle", "-"), ) self._wire_lines.append(line) - for line in self._wire_lines: self._ax.add_line(line) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index d10812be39d..3962d27930e 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -344,11 +344,8 @@ def wire1(x): assert w.get_color() == "orange" # Wires are orange and cyan - wire_options = { - 0: {"color": "orange"}, - 1: {"color": "cyan"} - } - _,ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + wire_options = {0: {"color": "orange"}, 1: {"color": "cyan"}} + _, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) assert ax.lines[0].get_color() == "orange" assert ax.lines[1].get_color() == "cyan" @@ -356,17 +353,18 @@ def wire1(x): @qml.qnode(dev) def wire1(x): for w in range(10): - qml.Hadamard(w) + qml.Hadamard(w) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) - # Make all wires cyan and bold, + # 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(wire1, wire_options=wire_options)(0.52) + wire_options = { + "color": "cyan", + "linewidth": 5, + 2: {"linestyle": "--", "color": "red"}, + 6: {"linestyle": "--", "color": "orange"}, + } + _, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) for i, w in enumerate(ax.lines): if i == 2: From 4ae5f4d883e573d835ac3484ab8891c9c497eac3 Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 18:34:12 +0900 Subject: [PATCH 10/39] Resolve Pylint Error --- tests/drawer/test_draw_mpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 3962d27930e..6f35b6204c9 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -351,7 +351,7 @@ def wire1(x): assert ax.lines[1].get_color() == "cyan" @qml.qnode(dev) - def wire1(x): + def wire2(x): for w in range(10): qml.Hadamard(w) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) @@ -364,7 +364,7 @@ def wire1(x): 2: {"linestyle": "--", "color": "red"}, 6: {"linestyle": "--", "color": "orange"}, } - _, ax = qml.draw_mpl(wire1, wire_options=wire_options)(0.52) + _, ax = qml.draw_mpl(wire2, wire_options=wire_options)(0.52) for i, w in enumerate(ax.lines): if i == 2: From eb02153cfd977809e74086d0b24a79d557ee73d3 Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 18:51:54 +0900 Subject: [PATCH 11/39] Simplify testing --- tests/drawer/test_draw_mpl.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 6f35b6204c9..2f7ba5bc455 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -330,32 +330,25 @@ def test_wire_options(self): # Define the quantum function with @qml.qnode @qml.qnode(dev) - def wire1(x): - qml.RX(x, wires=0) - qml.Hadamard(wires=1) - qml.CNOT(wires=[0, 1]) + def f_circ(x): + 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(wire1, wire_options=wire_options)(0.52) + _, 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(wire1, wire_options=wire_options)(0.52) + _, 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" - @qml.qnode(dev) - def wire2(x): - for w in range(10): - 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 = { @@ -364,7 +357,7 @@ def wire2(x): 2: {"linestyle": "--", "color": "red"}, 6: {"linestyle": "--", "color": "orange"}, } - _, ax = qml.draw_mpl(wire2, wire_options=wire_options)(0.52) + _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) for i, w in enumerate(ax.lines): if i == 2: From 63a9d076bbe65b9ab445e581425d81b7e46defbe Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 19:20:17 +0900 Subject: [PATCH 12/39] pylint format --- tests/drawer/test_draw_mpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 2f7ba5bc455..d9c238438cd 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -328,9 +328,9 @@ def test_wire_options(self): assert w.get_color() == "black" assert w.get_linewidth() == 4 - # Define the quantum function with @qml.qnode @qml.qnode(dev) def f_circ(x): + """Circuit on ten qubits.""" for w in range(10): qml.Hadamard(w) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) From 29eae3275a79bc0a8c2b221e59e54df57c243324 Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 20:20:24 +0900 Subject: [PATCH 13/39] resolve test case conflict --- pennylane/drawer/mpldrawer.py | 54 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index b7f801520d8..802470161d2 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -293,31 +293,35 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None if wire_options is None: wire_options = {} - - # Separate default options from specific wire options - default_options = {k: v for k, v in wire_options.items() if isinstance(k, str)} - wire_specific_options = {k: v for k, v in wire_options.items() if isinstance(k, int)} - - # Define defaults if "color" and "linewidth" aren't specified in default_options - default_color = default_options.get("color", "black") - default_linewidth = default_options.get("linewidth", 1) - - # 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 = {**default_options, **specific_options} - - # Create Line2D with the combined options - line = plt.Line2D( - (-1, self.n_layers), - (wire, wire), - zorder=1, - color=line_options.get("color", default_color), - linewidth=line_options.get("linewidth", default_linewidth), - linestyle=line_options.get("linestyle", "-"), - ) - self._wire_lines.append(line) + self._wire_lines = [ + plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, **wire_options) + for wire in range(self.n_wires) + ] + else: + # Separate default options from specific wire options + default_options = {k: v for k, v in wire_options.items() if isinstance(k, str)} + wire_specific_options = {k: v for k, v in wire_options.items() if isinstance(k, int)} + + # Define defaults if "color" and "linewidth" aren't specified in default_options + default_color = default_options.get("color", "black") + default_linewidth = default_options.get("linewidth", 1) + + # 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 = {**default_options, **specific_options} + + # Create Line2D with the combined options + line = plt.Line2D( + (-1, self.n_layers), + (wire, wire), + zorder=1, + color=line_options.get("color", default_color), + linewidth=line_options.get("linewidth", default_linewidth), + linestyle=line_options.get("linestyle", "-"), + ) + self._wire_lines.append(line) for line in self._wire_lines: self._ax.add_line(line) From c3c01245668223f7877e9a10b28c9f43f18d5799 Mon Sep 17 00:00:00 2001 From: zazabap Date: Sat, 2 Nov 2024 20:52:41 +0900 Subject: [PATCH 14/39] resolve pylint --- tests/drawer/test_draw_mpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index d9c238438cd..75370e78a97 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -331,6 +331,7 @@ def test_wire_options(self): @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)) From 155adb47c43719560c842968df453b7626cbe87b Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:30:33 +0900 Subject: [PATCH 15/39] Update doc/releases/changelog-dev.md Co-authored-by: David Wierichs --- doc/releases/changelog-dev.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index f68104d88d9..27592e29f9b 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -6,7 +6,8 @@

Improvements 🛠

-* 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`. +* 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) * Added `qml.devices.qubit_mixed` module for mixed-state qubit device support. This module introduces: From db5f470f5cc1ad1e5f7969ffd692eb91a733326d Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:30:42 +0900 Subject: [PATCH 16/39] Update doc/code/qml_drawer.rst Co-authored-by: David Wierichs --- doc/code/qml_drawer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/code/qml_drawer.rst b/doc/code/qml_drawer.rst index 3ed3fdafcdf..06963290027 100644 --- a/doc/code/qml_drawer.rst +++ b/doc/code/qml_drawer.rst @@ -69,7 +69,7 @@ as `color`, `linestyle`, and `linewidth` allows for per-wire customization. qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliZ(0) @ qml.PauliY(1)) - # Draw the circuit and save the plot + # Draw the circuit fig, ax = qml.draw_mpl(wire1)(0.52) # All wires are orange From 196bfa3f7de969ed56b8c9cfcb89d0a927b5f3a5 Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:31:00 +0900 Subject: [PATCH 17/39] Update doc/code/qml_drawer.rst Co-authored-by: David Wierichs --- doc/code/qml_drawer.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/code/qml_drawer.rst b/doc/code/qml_drawer.rst index 06963290027..2283f327d25 100644 --- a/doc/code/qml_drawer.rst +++ b/doc/code/qml_drawer.rst @@ -57,7 +57,8 @@ The ``wire_options`` dictionary allows customization of the formatting for the w the circuit visualization. This dictionary may contain standard matplotlib options for line formatting, as well as entries with wire labels as keys and corresponding dictionaries as values for specific wire line styling. For example, using keys such -as `color`, `linestyle`, and `linewidth` allows for per-wire customization. +as `color`, `linestyle`, and `linewidth` within these inner dictionaries allows for +per-wire customization. .. code-block:: python From 89c964c7e958e14147c6318ce23f7b32e0ed0d5c Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:32:59 +0900 Subject: [PATCH 18/39] Update tests/drawer/test_draw_mpl.py Co-authored-by: David Wierichs --- tests/drawer/test_draw_mpl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 75370e78a97..71d789e71a9 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -349,6 +349,7 @@ def f_circ(x): 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 From 4fb134ac5b0748cdd59ee48550171deaa32641be Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 00:33:17 +0900 Subject: [PATCH 19/39] Update tests/drawer/test_draw_mpl.py Co-authored-by: David Wierichs --- tests/drawer/test_draw_mpl.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 71d789e71a9..700c71803b5 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -365,11 +365,14 @@ def f_circ(x): if i == 2: assert w.get_color() == "red" assert w.get_linestyle() == "--" + assert w.get_linewidth() == 1 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 plt.close() From a9935e4d88fe63604a07ae56b3914f6a52c4192a Mon Sep 17 00:00:00 2001 From: zazabap Date: Tue, 5 Nov 2024 00:37:54 +0900 Subject: [PATCH 20/39] Universal linewidth is 5, only 2 and 6 are design to be 1 --- tests/drawer/test_draw_mpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 700c71803b5..cc957d6aeea 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -356,8 +356,8 @@ def f_circ(x): wire_options = { "color": "cyan", "linewidth": 5, - 2: {"linestyle": "--", "color": "red"}, - 6: {"linestyle": "--", "color": "orange"}, + 2: {"linestyle": "--", "color": "red", "linewidth": 1}, + 6: {"linestyle": "--", "color": "orange", "linewidth": 1}, } _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) From c349edc14988949e3eb4d04ee3921c472d87f1a6 Mon Sep 17 00:00:00 2001 From: zazabap Date: Tue, 5 Nov 2024 17:32:40 +0900 Subject: [PATCH 21/39] Add dictionary check and update the function --- pennylane/drawer/mpldrawer.py | 16 ++++++++-------- tests/drawer/test_draw_mpl.py | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index 802470161d2..37d041564cd 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -299,26 +299,26 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None ] else: # Separate default options from specific wire options - default_options = {k: v for k, v in wire_options.items() if isinstance(k, str)} - wire_specific_options = {k: v for k, v in wire_options.items() if isinstance(k, int)} + 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)} - # Define defaults if "color" and "linewidth" aren't specified in default_options - default_color = default_options.get("color", "black") - default_linewidth = default_options.get("linewidth", 1) + # Define defaults if "color" and "linewidth" aren't specified in global_options + global_color = global_options.get("color", "black") + global_linewidth = global_options.get("linewidth", 1) # 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 = {**default_options, **specific_options} + line_options = {**global_options, **specific_options} # Create Line2D with the combined options line = plt.Line2D( (-1, self.n_layers), (wire, wire), zorder=1, - color=line_options.get("color", default_color), - linewidth=line_options.get("linewidth", default_linewidth), + color=line_options.get("color", global_color), + linewidth=line_options.get("linewidth", global_linewidth), linestyle=line_options.get("linestyle", "-"), ) self._wire_lines.append(line) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index cc957d6aeea..7fed01bfcb0 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -375,6 +375,28 @@ def f_circ(x): 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() From f62df6ca9d04668d18c085bdd9496abe4cfa19d6 Mon Sep 17 00:00:00 2001 From: zazabap Date: Tue, 5 Nov 2024 17:38:33 +0900 Subject: [PATCH 22/39] remove redundancy --- pennylane/drawer/mpldrawer.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index 37d041564cd..b8219ccf63b 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -302,10 +302,6 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None 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)} - # Define defaults if "color" and "linewidth" aren't specified in global_options - global_color = global_options.get("color", "black") - global_linewidth = global_options.get("linewidth", 1) - # Adding wire lines with individual styles based on wire_options self._wire_lines = [] for wire in range(self.n_wires): @@ -317,9 +313,9 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None (-1, self.n_layers), (wire, wire), zorder=1, - color=line_options.get("color", global_color), - linewidth=line_options.get("linewidth", global_linewidth), - linestyle=line_options.get("linestyle", "-"), + color=line_options.get("color"), + linewidth=line_options.get("linewidth"), + linestyle=line_options.get("linestyle"), ) self._wire_lines.append(line) From 7f95f26cd511dc5e0c0abddc557220ecb554e4f2 Mon Sep 17 00:00:00 2001 From: dwierichs Date: Tue, 5 Nov 2024 10:08:01 +0100 Subject: [PATCH 23/39] docstring --- 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 | 51 +--------------------- pennylane/drawer/draw.py | 31 +++++++++++-- pennylane/drawer/tape_mpl.py | 37 ++++++++++++---- 5 files changed, 56 insertions(+), 63 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{a Date: Tue, 5 Nov 2024 18:18:21 +0900 Subject: [PATCH 24/39] Update tests/drawer/test_draw_mpl.py Co-authored-by: David Wierichs --- tests/drawer/test_draw_mpl.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/drawer/test_draw_mpl.py b/tests/drawer/test_draw_mpl.py index 7fed01bfcb0..23ca78d19a2 100644 --- a/tests/drawer/test_draw_mpl.py +++ b/tests/drawer/test_draw_mpl.py @@ -356,7 +356,7 @@ def f_circ(x): wire_options = { "color": "cyan", "linewidth": 5, - 2: {"linestyle": "--", "color": "red", "linewidth": 1}, + 2: {"linestyle": "--", "color": "red"}, 6: {"linestyle": "--", "color": "orange", "linewidth": 1}, } _, ax = qml.draw_mpl(f_circ, wire_options=wire_options)(0.52) @@ -365,7 +365,7 @@ def f_circ(x): if i == 2: assert w.get_color() == "red" assert w.get_linestyle() == "--" - assert w.get_linewidth() == 1 + assert w.get_linewidth() == 5 elif i == 6: assert w.get_color() == "orange" assert w.get_linestyle() == "--" From 084461234043b911d836782fd7a71b3f8e7a01b7 Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:19:04 +0900 Subject: [PATCH 25/39] Update pennylane/drawer/mpldrawer.py Co-authored-by: David Wierichs --- pennylane/drawer/mpldrawer.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index b8219ccf63b..d345a51b7fd 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -313,9 +313,7 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None (-1, self.n_layers), (wire, wire), zorder=1, - color=line_options.get("color"), - linewidth=line_options.get("linewidth"), - linestyle=line_options.get("linestyle"), + **line_options, ) self._wire_lines.append(line) From 0293868e50146faaf2cb9d10881de6f6afa68290 Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Tue, 5 Nov 2024 18:19:22 +0900 Subject: [PATCH 26/39] Update doc/releases/changelog-dev.md Co-authored-by: David Wierichs --- doc/releases/changelog-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 4af7367eddb..e21af08d8e4 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -8,7 +8,7 @@ * 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) + [(#6486)](https://github.com/PennyLaneAI/pennylane/pull/6486) * Added `qml.devices.qubit_mixed` module for mixed-state qubit device support. This module introduces: - A new API for mixed-state operations From 437a410966645eaef17859c40c4a54d82757d298 Mon Sep 17 00:00:00 2001 From: ringo-but-quantum <> Date: Tue, 5 Nov 2024 09:51:14 +0000 Subject: [PATCH 27/39] [no ci] bump nightly version --- pennylane/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/_version.py b/pennylane/_version.py index 4f4b04537f8..d359806dcf1 100644 --- a/pennylane/_version.py +++ b/pennylane/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.40.0-dev5" +__version__ = "0.40.0-dev6" From f4ba6c8d1b82a1bafa20442a3a2e595cf0278bcd Mon Sep 17 00:00:00 2001 From: zazabap Date: Tue, 5 Nov 2024 19:30:27 +0900 Subject: [PATCH 28/39] Reformat --- pennylane/drawer/draw.py | 6 +++--- pennylane/drawer/tape_mpl.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index 6b19484cffe..6dda8561403 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -574,13 +574,13 @@ def circuit2(x, y): Additionally, ``wire_options`` may contain wire labels as keys and dictionaries with keyword-value pairs of matplotlib options as values, which will control the line style for - the respective individual wire. + the respective individual wire. .. 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 + '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) diff --git a/pennylane/drawer/tape_mpl.py b/pennylane/drawer/tape_mpl.py index b3a92ac1fcc..9fb1409dc56 100644 --- a/pennylane/drawer/tape_mpl.py +++ b/pennylane/drawer/tape_mpl.py @@ -462,13 +462,13 @@ def tape_mpl( Additionally, ``wire_options`` may contain wire labels as keys and dictionaries with keyword-value pairs of matplotlib options as values, which will control the line style for - the respective individual wire. + the respective individual wire. .. 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 + '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) From 8a19ed711b4d6a4501f9826c3e0366eb08f71af5 Mon Sep 17 00:00:00 2001 From: zazabap Date: Tue, 5 Nov 2024 20:16:29 +0900 Subject: [PATCH 29/39] Update Comments --- pennylane/drawer/mpldrawer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index d345a51b7fd..c70e09f9470 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -298,7 +298,7 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None for wire in range(self.n_wires) ] else: - # Separate default options from specific wire options + # 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)} From 0474d6983e0190b26b35934e8a744f6a2bd0225f Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:13:13 +0900 Subject: [PATCH 30/39] Update pennylane/drawer/mpldrawer.py Co-authored-by: Astral Cai --- pennylane/drawer/mpldrawer.py | 42 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/pennylane/drawer/mpldrawer.py b/pennylane/drawer/mpldrawer.py index c70e09f9470..64e92a50cfe 100644 --- a/pennylane/drawer/mpldrawer.py +++ b/pennylane/drawer/mpldrawer.py @@ -293,29 +293,25 @@ def __init__(self, n_layers, n_wires, c_wires=0, wire_options=None, figsize=None if wire_options is None: wire_options = {} - self._wire_lines = [ - plt.Line2D((-1, self.n_layers), (wire, wire), zorder=1, **wire_options) - for wire in range(self.n_wires) - ] - else: - # 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) + + # 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) From 574f31110e18a65c0e4c5c663b36f96f9d6b1282 Mon Sep 17 00:00:00 2001 From: Shiwen An <97461865+zazabap@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:13:26 +0900 Subject: [PATCH 31/39] Update pennylane/drawer/draw.py Co-authored-by: Astral Cai --- pennylane/drawer/draw.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index 6dda8561403..2a3f1202560 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -572,9 +572,8 @@ def circuit2(x, y): :target: javascript:void(0); - Additionally, ``wire_options`` may contain wire labels as keys and dictionaries with - keyword-value pairs of matplotlib options as values, which will control the line style for - the respective individual wire. + 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 From 27ac0d22a5cdd125c01966add06d749741529616 Mon Sep 17 00:00:00 2001 From: zazabap Date: Wed, 6 Nov 2024 10:19:26 +0900 Subject: [PATCH 32/39] update function description --- pennylane/drawer/tape_mpl.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pennylane/drawer/tape_mpl.py b/pennylane/drawer/tape_mpl.py index 9fb1409dc56..b1aa8f93af4 100644 --- a/pennylane/drawer/tape_mpl.py +++ b/pennylane/drawer/tape_mpl.py @@ -460,9 +460,8 @@ def tape_mpl( :width: 60% :target: javascript:void(0); - Additionally, ``wire_options`` may contain wire labels as keys and dictionaries with - keyword-value pairs of matplotlib options as values, which will control the line style for - the respective individual wire. + 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 From 373f217f9f8ff18bcdb534f01f5802243211a3ab Mon Sep 17 00:00:00 2001 From: zazabap Date: Wed, 6 Nov 2024 10:57:09 +0900 Subject: [PATCH 33/39] modify to fit description style --- pennylane/drawer/draw.py | 2 +- pennylane/drawer/tape_mpl.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index 2a3f1202560..d2ce0898645 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -572,7 +572,7 @@ def circuit2(x, y): :target: javascript:void(0); - Additionally, ``wire_options`` may contain sub-dictionaries of matplotlib options assigned + Additionally, ``wire_options`` may contain subdictionaries of matplotlib options assigned to separate wire labels, which will control the line style for the respective individual wires. .. code-block:: python diff --git a/pennylane/drawer/tape_mpl.py b/pennylane/drawer/tape_mpl.py index b1aa8f93af4..5904e2ba42e 100644 --- a/pennylane/drawer/tape_mpl.py +++ b/pennylane/drawer/tape_mpl.py @@ -460,7 +460,7 @@ def tape_mpl( :width: 60% :target: javascript:void(0); - Additionally, ``wire_options`` may contain sub-dictionaries of matplotlib options assigned + Additionally, ``wire_options`` may contain subdictionaries of matplotlib options assigned to separate wire labels, which will control the line style for the respective individual wires. .. code-block:: python From cf26dea0b768e6e131e84ee92ab1d3a610d1b63e Mon Sep 17 00:00:00 2001 From: zazabap Date: Wed, 6 Nov 2024 11:05:03 +0900 Subject: [PATCH 34/39] Revert "update function description" This reverts commit 27ac0d22a5cdd125c01966add06d749741529616. --- pennylane/drawer/tape_mpl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/drawer/tape_mpl.py b/pennylane/drawer/tape_mpl.py index 5904e2ba42e..b1aa8f93af4 100644 --- a/pennylane/drawer/tape_mpl.py +++ b/pennylane/drawer/tape_mpl.py @@ -460,7 +460,7 @@ def tape_mpl( :width: 60% :target: javascript:void(0); - Additionally, ``wire_options`` may contain subdictionaries of matplotlib options assigned + 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 From cd0bdca9d1df9202e789ffe3a3f0ed012934d12f Mon Sep 17 00:00:00 2001 From: zazabap Date: Wed, 6 Nov 2024 11:12:30 +0900 Subject: [PATCH 35/39] Revert "modify to fit description style" This reverts commit 373f217f9f8ff18bcdb534f01f5802243211a3ab. --- pennylane/drawer/draw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/drawer/draw.py b/pennylane/drawer/draw.py index d2ce0898645..2a3f1202560 100644 --- a/pennylane/drawer/draw.py +++ b/pennylane/drawer/draw.py @@ -572,7 +572,7 @@ def circuit2(x, y): :target: javascript:void(0); - Additionally, ``wire_options`` may contain subdictionaries of matplotlib options assigned + 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 From ce1b9b173495e97a667a49ada9b87e6c734cc856 Mon Sep 17 00:00:00 2001 From: dwierichs Date: Wed, 6 Nov 2024 09:02:30 +0100 Subject: [PATCH 36/39] trigger CI From 654bdf157ef620793a7010ddaa92569264f287d9 Mon Sep 17 00:00:00 2001 From: ringo-but-quantum <> Date: Wed, 6 Nov 2024 09:50:55 +0000 Subject: [PATCH 37/39] [no ci] bump nightly version --- pennylane/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/_version.py b/pennylane/_version.py index d359806dcf1..9742ee34e30 100644 --- a/pennylane/_version.py +++ b/pennylane/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.40.0-dev6" +__version__ = "0.40.0-dev7" From c3ea59e4bd1d6e33038a6f835b95c0ba9f6e5c2c Mon Sep 17 00:00:00 2001 From: ringo-but-quantum <> Date: Thu, 7 Nov 2024 09:51:15 +0000 Subject: [PATCH 38/39] [no ci] bump nightly version --- pennylane/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/_version.py b/pennylane/_version.py index 9742ee34e30..8a038f25c6b 100644 --- a/pennylane/_version.py +++ b/pennylane/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.40.0-dev7" +__version__ = "0.40.0-dev8" From 9f1990ae44f4ed3f6df0c7f495ae5b42b8e1b852 Mon Sep 17 00:00:00 2001 From: ringo-but-quantum <> Date: Fri, 8 Nov 2024 09:51:14 +0000 Subject: [PATCH 39/39] [no ci] bump nightly version --- pennylane/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/_version.py b/pennylane/_version.py index 8a038f25c6b..4012d0f128d 100644 --- a/pennylane/_version.py +++ b/pennylane/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.40.0-dev8" +__version__ = "0.40.0-dev9"