-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 control_keys protocol #4490
Conversation
Use control keys in circuit construction to block controlled gates "earliest" append method from falling back to before the measurement.
@95-martin-orion This is ready for review |
def _control_key_names_(self): | ||
return {key for op in self.all_operations() for key in protocols.control_key_names(op)} |
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.
[No change needed] We'll need to be careful about this - the circuit itself isn't controlled, just the gates inside it.
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.
Yeah, my initial thought was to have this return only external keys like CircuitOperations. But for diagramming we'll need a list of all the control keys so we can draw the creg lines.
That said, I agree it's odd that the Circuit would have different list than the CircuitOperation. Maybe it's best to have them both hide internal keys, and the diagramming tool can just iterate the circuit's ops and aggregate the control key names manually.
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.
(Note to self: I think it's better to have the two be consistent, or people will get confused. Probably best to provide an explicit include_internal
flag in control_key_names()
).
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 don't think we should be exposing internal cbits as control_keys
. This would really make the semantics confusing as you noted. control_keys
for any entity (Operation
, CircuitOperation
or Circuit
) should mean "The classical bits that need to be True for this entity to run". So internal keys are not really part of this. We can have a separate protocol to get the internal keys but I don't see what purpose it can serve that cannot already be served by measurement_keys
protocol.
The diagram can iterate through internal operations to figure out which of the measurement keys we need to draw a creg for.
from cirq._doc import doc_private | ||
|
||
|
||
class SupportsControlKey(Protocol): |
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.
Clean up docstrings in this file - it looks like there was a copy & replace from measurement keys, but the meaning doesn't line up.
k = value.MeasurementKey.parse_serialized(k).name | ||
k_new = self.measurement_key_map.get(k, k) | ||
k_new = key_map.get(k_new, k_new) | ||
if k_new != k: | ||
new_map[k] = k_new | ||
new_op = self.replace(measurement_key_map=new_map) | ||
if len(new_op._measurement_key_names_()) != len(self._measurement_key_names_()): | ||
if len(new_op._measurement_key_names_()) != len(self._measurement_key_names_()) or len( |
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 we also need a check that this doesn't cause any new conflicts between control keys and measurement keys. Maybe check len(measurement_keys & control_keys)
is unchanged. I'm pretty sure we need all three checks. Write some unit tests that cover each case.
I think there is a conflation between some slightly different sets of classical data here that's causing confusion.
If we need to compute "external control keys" (type 3 above) anywhere, we can just resort to |
def _control_key_names_(self): | ||
return {key for op in self.all_operations() for key in protocols.control_key_names(op)} |
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 don't think we should be exposing internal cbits as control_keys
. This would really make the semantics confusing as you noted. control_keys
for any entity (Operation
, CircuitOperation
or Circuit
) should mean "The classical bits that need to be True for this entity to run". So internal keys are not really part of this. We can have a separate protocol to get the internal keys but I don't see what purpose it can serve that cannot already be served by measurement_keys
protocol.
The diagram can iterate through internal operations to figure out which of the measurement keys we need to draw a creg for.
@smitsanghavi This is a good breakdown. Actually what I am shooting for in the control_keys protocol is a union of types 1 and 3, to be interpreted as "the control keys that need to be defined prior to running this operation". Or in other words, the classical inputs to this function/operation/subcircuit. This corresponds to measurement_keys protocol as being the classical outputs of the same. I'm interested to understand more about the CBits augmentation. Are you proposing a new class to represent them or just the protocol? One big difference I see between qubits and cbits is that cbits can be dynamically allocated. They aren't yet, but as we start introducing flow control features like So I was hoping to keep feedforward on the simple side; just base it on measurement keys until some of the other issues like flow control, IQ points, non-unique measurements were better fleshed out. Ultimately I think we'll need something like CValue that can be a range of different data types or lists, and have measurement operations like "xor", "and", "or", "sum", "concat", etc (#4274 (comment)) that operate on different subtypes of CValue. But that's all obviously very nebulous and hand wavy at this point. |
Discussed in the classical control sync: |
e56b2fe
to
fc652e3
Compare
while k > 0: | ||
k -= 1 | ||
if not self._can_commute_past(k, op): | ||
moment = self._moments[k] | ||
if moment.operates_on(op_qubits) or any( |
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.
any
is not the correct thing here. Use len(...)==0
, or bool(...)
, or just nothing.
Closing for now in favor of #4610. Will revisit extern control keys later. |
Use control keys in circuit construction to block controlled gates "earliest" append method from falling back to before the measurement. Parts 5&7 of https://tinyurl.com/cirq-feedforward. (I grouped them together in a single PR so that circuit.append could be a POC that control_keys protocol design works as intended). Replaces/simplifies #4490 since we will handle "extern" control keys in subcircuits as a separate PR.
Use control keys in circuit construction to block controlled gates "earliest" append method from falling back to before the measurement. Parts 5&7 of https://tinyurl.com/cirq-feedforward. (I grouped them together in a single PR so that circuit.append could be a POC that control_keys protocol design works as intended). Replaces/simplifies quantumlib#4490 since we will handle "extern" control keys in subcircuits as a separate PR.
Use control keys in circuit construction to block controlled gates "earliest" append method from falling back to before the measurement. Parts 5&7 of https://tinyurl.com/cirq-feedforward. (I grouped them together in a single PR so that circuit.append could be a POC that control_keys protocol design works as intended). Replaces/simplifies quantumlib#4490 since we will handle "extern" control keys in subcircuits as a separate PR.
Use control keys in circuit construction to block controlled gates "earliest" append method from falling back to before the measurement.
Parts 5&7 of https://tinyurl.com/cirq-feedforward. (I grouped them together in a single PR so that circuit.append could be a POC that control_keys protocol design works as intended).
Replaces #4466 since underlying measurement_keys has changed.