-
Notifications
You must be signed in to change notification settings - Fork 164
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
Add substitute_node_with_subgraph method to PyDiGraph #312
Conversation
This commit adds a new method substitute_node_with_subgraph that takes in a node id and a PyDiGraph object and then procedes to replace the specified node with the subgraph.
This commit leverage the substitute_node_with_subgraph method being added Qiskit/rustworkx#312 for the dagcircuit method substitute_node_with_dag.
Pull Request Test Coverage Report for Build 968084539
💛 - Coveralls |
Ok, I've updated this and I think it's ready for review now. There is a matching terra PR which shows this in use: Qiskit/qiskit#6302 |
This is unavoidable because we can't preserve the indices between the 2 graphs as there might be overlap and we're essentially just calling For the second half I'm actually not actually sure how node index 2 is getting added there. I agree it should be 7, let me dig into that with your example locally and see if I can figure out what's going on |
So I dug into this it's a behavior of petgraph's stable graph. It will reuse node indices after removal: https://github.com/petgraph/petgraph/blob/0.5.1/src/graph_impl/stable_graph/mod.rs#L246-L253 I was able to reproduce this manually with: graph = retworkx.PyDiGraph()
graph.add_nodes_from(list(range(5)))
graph.add_nodes_from(list(range(2)))
graph.remove_node(2)
res_manual = graph.add_parent(6, None, None)
print(res_manual) which returns 2. I'm guessing it does this to preserve memory. But, this caught me by surprise too, but then I haven't manually inspected the indices post removal like this before. When I've been using graphs with removals I been interacting with the indices programmatically and never looked at them directly. I think we should definitely document this in the class docstrings for |
Sure, that makes sense. I forgot about the return, sorry about that. |
/// when iterated over (although the same object will have a consistent | ||
/// order when iterated over multiple times). | ||
/// | ||
#[text_signature = "(self, node, other, edge_map_fn, /, node_filter=None, edge_weight_map=None)"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think edge_map_fn
should be optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required right now because we without it we don't know what to do with edges to or from node
. If we switched it to optional what do you think the default behavior should it was not set? The only option I could think of is to just drop all the edges into or out of node
if this wasn't set, but if we did this it wouldn't really feel like it was substituting the node with a graph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a typo?
#[text_signature = "(self, node, other, edge_map_fn, /, node_filter=None, edge_weight_map=None)"] | |
#[text_signature = "(self, node, other, edge_map_fn, node_filter=None, edge_weight_map=None)"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually intentional, the /
indicates the end of positional only arguments (it's part of the cPython interface and is actually a valid python syntax for >=3.8). See the docs for the rust python interface here: https://pyo3.rs/v0.9.2/function.html#making-the-function-signature-available-to-python which explains this.
Co-authored-by: Luciano Bello <[email protected]>
* Use retworkx for substitute_node_with_dag This commit leverage the substitute_node_with_subgraph method being added Qiskit/rustworkx#312 for the dagcircuit method substitute_node_with_dag. * DNM: Add retworkx from PR branch to CI * Fix handling of input dag with direct edge from input to output * Update requirements for testing * Run black * Avoid node copy * Avoid op func call overhead * Fix lint * Expand substitute tests * Make failing test deterministic * Fix qasm example * Fix lint * Update retworkx source path * Fix rebase issues * Bump minimum retworkx version to latest release * Reduce iterations building wire maps * Use a plain list comprehension instead of a lambda map * Apply suggestions from code review Co-authored-by: Kevin Krsulich <[email protected]> * Improve code comments * Add reno touting performance benefits Co-authored-by: Kevin Krsulich <[email protected]> Co-authored-by: Jake Lishman <[email protected]> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit adds a new method substitute_node_with_subgraph that takes
in a node id and a PyDiGraph object and then procedes to replace the
specified node with the subgraph.
TODO:
substitute_node_with_dag