rustworkx icon indicating copy to clipboard operation
rustworkx copied to clipboard

Suggestion: a method to get a node index by a unique value

Open abgros opened this issue 6 months ago • 2 comments

Consider a graph like this:

graph = rx.PyDiGraph()
graph.add_node("a")
graph.add_node("b")
graph.add_node("c")

Say I want to find out what index the value b is at. The naïve implementation looks like:

def index_of(graph, value):
    return next((i for i in graph.node_indices() if graph[i] == value), None)

This is obviously very inefficient since it does a linear search across the entire graph. Instead, what I tend to do is create a separate hashmap which maps values to indices. This hashmap needs to be updated every time a node is added or removed from the graph. Also, we have to make sure that no duplicate nodes are added to the graph. It would be nice if rustworkx had a built-in way to do this. For example:

graph = rx.PyDiGraph(unique_values = True)
graph.add_node("a")
graph.add_node("b")
graph.add_node("c")
print(graph.index_of("b")) # 1

abgros avatar May 29 '25 19:05 abgros

I think this is closely related to #496. Which admittedly is an issue from early on in the library.

This is obviously very inefficient since it does a linear search across the entire graph. Instead, what I tend to do is create a separate hashmap which maps values to indices. This hashmap needs to be updated every time a node is added or removed from the graph. Also, we have to make sure that no duplicate nodes are added to the graph. It would be nice if rustworkx had a built-in way to do this. For example:

So there are two interesting points about this:

  1. rustworkx node values do not need to be hashable! Some of it comes from the Qiskit days. The first node values were quantum gates.
  2. There's a non-trivial overhead of hashing on every node insertion

The most used pattern for your use case is to keep a separate dictionary with the mapping of node ids <-> node values. Despite the overhead of the dictionary, users still report to us that doing Python -> rustworkx -> Python is faster than pure Python code.

I think one day we could possibly the structure described in #496. But that would be a big effort.

IvanIsCoding avatar May 30 '25 02:05 IvanIsCoding

There is also a method to look up a node index by the node data payload. You're looking for: https://www.rustworkx.org/apiref/rustworkx.PyDiGraph.find_node_by_weight.html

mtreinish avatar May 30 '25 19:05 mtreinish