Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update mpl_draw() to fix multigraph plots #1204

Merged
merged 13 commits into from
Jun 10, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fixes the plots of multigraphs using the `mpl_draw()` function. Refer to
`#12345 <https://github.com/Qiskit/rustworkx/issues/774>` for more
details.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The release notes would be better if you actually drew a multigraph with mpl_draw as an example. You can use

as an example, it becomes this: https://www.rustworkx.org/release_notes.html#new-features

other:
- |
The radius of the edges of self-loops in multigraphs is set to `0.25`.
The edge labels are offset accordingly.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the other section

17 changes: 16 additions & 1 deletion rustworkx/visualization/matplotlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,15 @@ def _connectionstyle(posA, posB, *args, **kwargs):
else:
line_width = width

# radius of edges
reverse_edge = [dst, src]
if (
len(np.where(np.all(edge_pos == reverse_edge, axis=(1, 2)))[0]) != 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this scales quadratically on the number of edges. O(E^2) is not ideal, if we plot a dense graph this is going to be a problem. You need to rewrite this condition using a set or something similar instead of naively looking through all the edges

): # if reverse edge is in `edge_pos`
rad = 0.25
else:
rad = 0.0

arrow = mpl.patches.FancyArrowPatch(
(x1, y1),
(x2, y2),
Expand All @@ -763,7 +772,7 @@ def _connectionstyle(posA, posB, *args, **kwargs):
mutation_scale=mutation_scale,
color=arrow_color,
linewidth=line_width,
connectionstyle=_connectionstyle,
connectionstyle=connectionstyle + f", rad = {rad}",
maxwell04-wq marked this conversation as resolved.
Show resolved Hide resolved
linestyle=style,
zorder=1,
) # arrows go behind nodes
Expand Down Expand Up @@ -1001,6 +1010,12 @@ def draw_edge_labels(
x1 * label_pos + x2 * (1.0 - label_pos),
y1 * label_pos + y2 * (1.0 - label_pos),
)
if (n2, n1) in labels.keys(): # loop
dy = np.abs(y2 - y1)
if n2 > n1:
y -= 0.25 * dy
else:
y += 0.25 * dy

if rotate:
# in degrees
Expand Down