Qiskit / rustworkx

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

Make the weight function of `dag_longest_path` aware of the nodes' data #1102

Closed TsafrirA closed 6 months ago

TsafrirA commented 6 months ago

What is the expected enhancement?

The weight function used in dag_longest_path gets passed only the indices of the nodes. As far as I can tell, this makes it impossible to use properties of the nodes themselves as part of the weight. The weight function is also oblivious to the graph, so you can't use .get_node_data().

I think the weight function should be aware of the nodes' data. Pass the node data instead of the index? Pass the graph itself as another argument to the weight function?

TsafrirA commented 6 months ago

(I am guessing this would apply to other functions in the dag_longest_... family, but I haven't checked)

jakelishman commented 6 months ago

Since the weight_fn is an arbitrary function, you can define one that closes over the DAG in Python space, so you can look up the node weights from within the weight_fn, something like this:

import rustworkx

dag = rustworkx.PyDiGraph()
nodes = dag.add_nodes_from([0, 4, 6, 3, 2, 8])
dag.add_edges_from([(node, nodes[-1], 0) for node in nodes[:-1]])

def weight_fn(source, target, weight):
    return dag[source] + dag[target] + weight

assert list(rustworkx.dag_longest_path(dag, weight_fn)) == [2, 5]

Quite often, the "longest path" doesn't need to examine the nodes at all (only the edges), and providing the node indices to the callable is more general than only providing their weights, because this way you could even do super weird stuff like look up node degree or things like that as well.

TsafrirA commented 6 months ago

You're absolutely right! Thanks.