-
Notifications
You must be signed in to change notification settings - Fork 141
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
Workaround isomorphism failure with node removals #115
Conversation
The dag_isomorphism module was forked from upstream petgraph to handle the PyDiGraph type and also to enable handling exceptions in the python check functions gracefully. However, when this was done it neglected that here were limitations with that module which causes failures in certain scenarios after node removals. This was because the upstream petgraph implementation was built on the Graph type instead of the StableGraph type. The only difference between these types is that StableGraph does not reuse indexes on removals but Graph does. This can cause there to be holes in the list of node ids. This breaks assumptions in multiple places of the VF2 implementation causing a panic if isomorphism checks are run on a PyDiGraph that has nodes removed. This commit worksaround this limitation by checking if we've removed nodes from the PyDiGraph object and if we have it iterates over the graph and clones it into a copy with a condensed set of node ids. This fix is less than ideal in that it results in a copy of the graph which will potentially have performance implications, especially for larger graphs. But after attempting to fix the VF2 implementation that seems to be a more involved project than I originally hoped. This will at least workaround the bug until a better more robust VF2 implementation can be written (and likely should be contributed back upstream to petgraph). Fixes Qiskit#27
@georgesbarron this should fix the issue and remove the need to always deepcopy in |
I did a quick synthetic test of the performance of this and removing the deepcopy from terra's dagcircuit by adding together to aqua operators: import time
from qiskit.aqua.operators import X, Y, Z, I, CX, T, H
c_op = (((CX ^ 3) ^ X) @
(H ^ 7) @
(X ^ Y ^ Z ^ I ^ X ^ X ^ X) @
(Y ^ (CX ^ 3)) @
(X ^ Y ^ Z ^ I ^ X ^ X ^ X))
newop = (((CX ^ 3) ^ X) @
(H ^ 7) @
(X ^ Y ^ Z ^ I ^ X ^ X ^ X) @
(Y ^ (CX ^ 3)) @
(X ^ Y ^ Z ^ I ^ X ^ X ^ X))
start = time.time()
c_op + newop
stop = time.time()
print(stop - start) With this PR (and the deepcopy removal from terra) the timed line took If you'd like to try and recreate this locally, the terra patch: diff --git a/qiskit/dagcircuit/dagcircuit.py b/qiskit/dagcircuit/dagcircuit.py
index b98b4092..81c958dd 100644
--- a/qiskit/dagcircuit/dagcircuit.py
+++ b/qiskit/dagcircuit/dagcircuit.py
@@ -773,12 +773,8 @@ class DAGCircuit:
return full_pred_map, full_succ_map
def __eq__(self, other):
- # TODO remove deepcopy calls after
- # https://github.com/mtreinish/retworkx/issues/27 is fixed
- slf = copy.deepcopy(self._multi_graph)
- oth = copy.deepcopy(other._multi_graph)
-
- return rx.is_isomorphic_node_match(slf, oth,
+ return rx.is_isomorphic_node_match(self._multi_graph,
+ other._multi_graph,
DAGNode.semantic_eq)
def topological_nodes(self): then I ran:
(this does require rust be installed) |
The dag_isomorphism module was forked from upstream petgraph to handle
the PyDiGraph type and also to enable handling exceptions in the python
check functions gracefully. However, when this was done it neglected
that here were limitations with that module which causes failures in
certain scenarios after node removals. This was because the upstream
petgraph implementation was built on the Graph type instead of the
StableGraph type. The only difference between these types is that
StableGraph does not reuse indexes on removals but Graph does. This
can cause there to be holes in the list of node ids. This breaks
assumptions in multiple places of the VF2 implementation causing a
panic if isomorphism checks are run on a PyDiGraph that has nodes
removed. This commit worksaround this limitation by checking if we've
removed nodes from the PyDiGraph object and if we have it iterates over
the graph and clones it into a copy with a condensed set of node ids.
This fix is less than ideal in that it results in a copy of the graph
which will potentially have performance implications, especially for
larger graphs. But after attempting to fix the VF2 implementation that
seems to be a more involved project than I originally hoped. This will
at least workaround the bug until a better more robust VF2
implementation can be written (and likely should be contributed back
upstream to petgraph).
Fixes #27