-
Notifications
You must be signed in to change notification settings - Fork 2.6k
QuantumCircuit and DAGCircuit updates for optional registers. #5498
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
QuantumCircuit and DAGCircuit updates for optional registers. #5498
Conversation
060ffbb
to
d13ef0e
Compare
acc066e
to
82897ed
Compare
82897ed
to
2eab8aa
Compare
2eab8aa
to
2e1d399
Compare
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 LGTM, just a few comments and questions inline
qiskit/dagcircuit/dagcircuit.py
Outdated
@@ -310,8 +314,7 @@ def _add_wire(self, wire): | |||
self.output_map[wire] = outp_node | |||
self._multi_graph.add_edge(inp_node._node_id, | |||
outp_node._node_id, | |||
{'name': wire_name, | |||
'wire': wire}) | |||
{'wire': wire}) |
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.
Do you think it would make sense to drop the dict wrapper here and just attach the bit/wire on the edge directly? We'd probably have to change some access patters from edge['wire']
to edge
not sure how much that is used.
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.
That's a good idea, it seems like only a handful of places check this property, so it seems a good time to remove the unneeded dict
.
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.
Added in 664485e .
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.
After starting Qiskit/rustworkx#252 I expect it was originally a dict because networkx only lets you weight edges with a dict of attributes instead of an object. After we switched to retworkx there wasn't really a reason to change it until now.
for creg in target_cregs | ||
if wire_map[bit] in creg) | ||
except StopIteration: | ||
raise DAGCircuitError('Did not find creg containing ' |
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 might be worth updating the docstring to add this error case under the DAGCircuitError
raise section. Something like, "also when the specified condition is not present in a classical register"
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.
Added in 686ed2c .
# Raise if wire_map maps condition creg on to more than one | ||
# creg in target DAG. | ||
raise DAGCircuitError('wire_map maps conditional ' | ||
'register onto more than one creg.') | ||
|
||
if 2**(bit.index) & cond_val: | ||
new_cond_val += 2**(wire_map[bit].index) | ||
if 2**(cond_creg[:].index(bit)) & cond_val: |
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 the [:]
just there to workaround around a Register not being a list and not having an index method?
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.
That's right. (Alternately, we could consider building the bit-> index dict
like we do elsewhere.)
carg1 = [node1.cargs[i] for i in range(0, len(node1.cargs))] | ||
carg2 = [node2.cargs[i] for i in range(0, len(node2.cargs))] |
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.
Wow, that's surprising nobody caught that we were putting qubits there until now.
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 seems like you'd hit this only if you were looking to run TemplateOptimization
on a circuit with more than one qreg
(but if you did, you'd hit it right away). Might be an edge case no one had run into yet, since its fairly new, and not in the preset pass managers.
qiskit/dagcircuit/dagnode.py
Outdated
@@ -102,27 +102,41 @@ def __str__(self): | |||
return str(id(self)) | |||
|
|||
@staticmethod | |||
def semantic_eq(node1, node2): | |||
def semantic_eq(node1, node2, bit_indices1, bit_indices2): |
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'm a bit concerned about this change from a backwards compat and interop PoV. Like someone could have been using semantic eq to compare dag nodes outside of DAGCircuit.__eq__
before right and this will now break them? Maybe making them optional and just having a fallback to node1_qargs = node1._qargs
if it's not specified.
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.
That makes sense. I'll add that (with a deprecation warning).
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.
Added in 0dc3d7a .
@@ -0,0 +1,6 @@ | |||
--- | |||
other: |
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 was thinking this might be an upgrade note instead, but I guess it is kind of an edge case. It's unlikely that people are depending on the name
field on the edge dict of a DAGCircuit
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.
Sure, moved in 664485e .
The other thing I forgot to ask in the earlier comments was what |
Appears not to be, though I'm not the most familiar with the code here. The only references I found to the wires/qargs was in |
Updates DAGCircuit._check_edgemap_registers: - Removes unused valregs and valreg arguments and associated code. - Renames edge_map and keyregs arguments to inbound_wires and inbound_regs. Removes need for proxy register map. - Renames several variables to match their outer context in DAGCircuit.substitute_node_with_dag.
These are redundant of preceding self.qregs updates, which already update self._qubits via the BlueprintCircuit.qregs setter.
2e1d399
to
3a306da
Compare
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.
LGTM< thanks for updating it. I think this is ready to go now.
raise DAGCircuitError("(qu)bit %s not found in %s" % | ||
(wire, amap)) |
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.
If this error ever got raised to the user it would make no sense. Not that it made much sense before. Being an internal function it should hopefully only come up during development and not be a big deal.
Summary
Following #5486 , updates
DAGCircuit
andQuantumCircuit
classes to support optional registers, and to prefer inspecting bits over registers where possible.Details and comments
on-hold until #5486 merges.Commits for just this PR (without #5486 ): https://github.com/Qiskit/qiskit-terra/pull/5498/files/45ba1d598141b90818c53abaadf1d64a80102e8b..d13ef0e35946d20facf569f2eadd65a93f678174