Add collect_runs() function#206
Conversation
|
Marked as on hold because I still need to write tests for the new function. I tested this manually by updating terra to use the new function instead of it's current implementation and it worked fine, but we need more direct test coverage here |
Pull Request Test Coverage Report for Build 396952472
💛 - Coveralls |
|
I think there are also some edge cases here when I ran qiskit-terra's tests with: index d56ca28d..a1480a5b 100644
--- a/qiskit/dagcircuit/dagcircuit.py
+++ b/qiskit/dagcircuit/dagcircuit.py
@@ -1378,29 +1378,13 @@ class DAGCircuit:
Nodes must have only one successor to continue the run.
"""
- group_list = []
-
- # Iterate through the nodes of self in topological order
- # and form tuples containing sequences of gates
- # on the same qubit(s).
- topo_ops = list(self.topological_op_nodes())
- nodes_seen = dict(zip(topo_ops, [False] * len(topo_ops)))
- for node in topo_ops:
- if node.name in namelist and node.condition is None \
- and not nodes_seen[node]:
- group = [node]
- nodes_seen[node] = True
- s = self._multi_graph.successors(node._node_id)
- while len(s) == 1 and \
- s[0].type == "op" and \
- s[0].name in namelist and \
- s[0].condition is None:
- group.append(s[0])
- nodes_seen[s[0]] = True
- s = self._multi_graph.successors(s[0]._node_id)
- if len(group) >= 1:
- group_list.append(tuple(group))
- return set(group_list)
+
+ def filter_fn(node):
+ return node.type == "op" and node.name in namelist and node.condition is None
+
+ group_list = rx.collect_runs(self._multi_graph, filter_fn)
+ print(group_list)
+ return set(tuple(x) for x in group_list)
def nodes_on_wire(self, wire, only_ops=False):
"""applied most of the tests work, but there are still some failures caused by differences in the returned runs between this function and what was in terra before. |
This commit adds a new algorithms function, collect_runs(), which is used to find a list of runs in a PyDiGraph object that match a specified condition. A run in this context is any linear path inside the graph. The condition is specified using a python function that will be passed a node's data payload/weight object and will return whether it matches the condition or not. The intended use case for this function is with qiskit-terra's PyDiGraph method collect_runs() which is implementing this algorithm currently in Python on top of PyDiGraph (it will also be used by a future method collect_1q_runs which is being added in Qiskit/qiskit#5431).
There was a bug in the collect_runs() method when there were multiple edges between a graph and its single successor node. Since neighbors_directed() returns an iterator over the edges and not the nodes it would have multiple entries in the succesors list despite only being a single node. This commit addresses that edge case by building a HashSet of the node indices in the succesors list and checking the length of that instead of using the raw successors list. That will contain no duplicate nodes and will identify if there is a path instead of splitting on multiple edges incorrectly.
3831c65 to
4c5d8eb
Compare
Co-authored-by: Lauren Capelluto <laurencapelluto@gmail.com>
|
I understand what is strange for the original implementation in qiskit-terra. The collect_run() implemented in this PR prevents such a duplication, and reports I confirmed that this change does not affect to current DAGCircuit usages within terra, collect_run is only used to collect consecutive CNOTs or 1q-gates. So I have little concern on the spec change induced by this PR. I like the spec implemented in this PR (it's clearer), so I suggest to
The above cases correspond with the circuits, respectively: I'm not sure adding circuit diagrams in docstring helps readers as they don't have information on edge directions. |
This commit documents and adds tests to assert that a node can only be in a single run in the output from the collect_runs() method. In terra the equivalent python function didn't have this additional constraint so this commit attempts to make it clear so the differences between the two implementations are understood by users.
Oh, that's interesting, I'm actually a bit surprised I basically just ported the logic from the terra
Yeah I agree with this, I've done this in: becd668
Yeah I'm not sure if circuit diagrams make sense in the docstring for retworkx tests, I can add them if you think it makes sense. For retworkx functions we can always leverage the graph drawer and |
This commit adds a new algorithms function, collect_runs(), which is
used to find a list of runs in a PyDiGraph object that match a specified
condition. A run in this context is any linear path inside the graph.
The condition is specified using a python function that will be passed a
node's data payload/weight object and will return whether it matches the
condition or not. The intended use case for this function is with
qiskit-terra's PyDiGraph method collect_runs() which is implementing
this algorithm currently in Python on top of PyDiGraph (it will also be
used by a future method collect_1q_runs which is being added in
Qiskit/qiskit#5431).
TODO