Qiskit / rustworkx

A high performance Python graph library implemented in Rust.
https://www.rustworkx.org
Apache License 2.0
1.13k stars 154 forks source link

`rx.visualization.mpl_draw()` does not apply an `edge_color` list to the correct edges #1308

Closed ryanhill1 closed 1 week ago

ryanhill1 commented 3 weeks ago

Information

What is the current behavior?

rustworkx.visualization.matplotlib.draw_edges() does not correctly apply edge_color of type list. Edge colors are not being applied to the edges of graph.edge_list() in the correct order. Issue sourced from: https://github.com/qBraid/qBraid/issues/802

What is the expected behavior?

The entries of a given edge_color list should be mapped to the correct edges, corresponding to the order of graph.edge_list().

Steps to reproduce the problem

The code below plots 3 nodes and 3 edges. Edge (c, a) should be colored blue. But if you run the code multiple times, you will find that the blue edge changes, and is not always (c, a).

import matplotlib.pyplot as plt
import rustworkx as rx
from rustworkx.visualization import mpl_draw

graph = rx.PyDiGraph()

a = graph.add_node("A")
b = graph.add_node("B")
c = graph.add_node("C")

graph.add_edges_from([(a, b, 0.1), (b, c, 1.2), (c, a, 2.0)])

edge_colors_dict = {(c, a): "blue"}
edge_colors = [edge_colors_dict.get((u, v), "grey") for u, v in graph.edge_list()]

mpl_draw(graph, edge_color=edge_colors, with_labels=True, labels=str)

plt.show()

If you pip install rustworkx<0.15.0, and run the code again, it works fine.

Therefore, I was able to trace this bug back the following commit: https://github.com/Qiskit/rustworkx/commit/646057ae16505293f48fcc260cfa384bcad78fbc

Using the draw_edges() function from before that commit (i.e. rustworkx version 0.14.2) resolves the issue. But the latest update seems to form an arrow_color list that is not consistent with the indexing of the edge_color list.

IvanIsCoding commented 3 weeks ago

We might need to revert that PR, not respecting the edge colours is a serious flaw. I would rather find a fix of course, but I think a wrong output for regular graphs is a bigger issue

frstyang commented 3 weeks ago

I noticed the same bug; I believe the issue is L638-L641 of matplotlib.py, where edge_pos is constructed as a set, which does not respect the order of edge_list when iterating over edge_pos later in the code. I manually changed this to a list and that worked for me.

https://github.com/Qiskit/rustworkx/blob/main/rustworkx/visualization/matplotlib.py#L638C1-L641C59

IvanIsCoding commented 3 weeks ago

I noticed the same bug; I believe the issue is L638-L641 of matplotlib.py, where edge_pos is constructed as a set, which does not respect the order of edge_list when iterating over edge_pos later in the code. I manually changed this to a list and that worked for me.

https://github.com/Qiskit/rustworkx/blob/main/rustworkx/visualization/matplotlib.py#L638C1-L641C59

Thanks for investigating. I will try to fix if the issue is simply iterables not preserving order