quantumlib / Cirq

A Python framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
Apache License 2.0
4.24k stars 1.01k forks source link

Why does `ControlledGate` have a notion of qubits #1973

Closed mpharrigan closed 5 years ago

mpharrigan commented 5 years ago

ControlledGate.control_qubits is a tuple of Qid (or Nones). I thought "gates" don't have qubits and that that is reserved for Operations.

c-poole commented 5 years ago

ControlledGate seems to use the control_qubits property primarily as a way of helping it interpret how to use a qubit list that has been provided to it by methods like _decompose_, _on_, and such. It is primarily being used decide which qubits in the provided list are controls and which are targets using a (seemingly?) undocumented convention that control qubits come earlier in the list. The flexibility that this provides is that you can specify a subset of the control qubits initially and use the resulting ControlledGate object as a Gate or Operation generator. I'm not sure if there is a need for this degree of flexibility in generation of operations though. It seems like ControlledGate is redundant if we have ControlledOperation. Edit: wrong word, typo

dabacon commented 5 years ago

This is to have controlled gates that are associated with control on some fixed qubits. I agree that it is confusing and argued against it in the original PR. It adds complexity, violates the usual case that gates do not have qubits, and leads to code that is only slightly nicer in the case that it is used.

Strilanc commented 5 years ago

I thought "gates" don't have qubits and that that is reserved for Operations.

It would be more accurate to say that a gate has some (but not necessarily only) unspecified qubits. A gate is a callable, plus convenience methods, that takes qubits and returns an operation.

dabacon commented 5 years ago

It would be more accurate to say that a gate has some (but not necessarily only) unspecified qubits. A gate is a callable, plus convenience methods, that takes qubits and returns an operation.

That's what's at debate. I think that including qubits in the constructor is conceptually confusing. Maybe a solution is to hide these sort of qubits in a class constructor (so they are only set if you come in from ControlledGate.controlled_from_fixed_qubits())

The other issue with this pattern is that it breaks any code that reasons "the only qubits this gate acts on are those that are operated on by the on method". There are other cases where Operation breaks this as well, and I worry a lot about these (I would bet there is already broken code for these types of operations)

mpharrigan commented 5 years ago

If you can have partially specified qubits, I'm led to ask why bother having a difference between Gate and Operation at all? There could be one object that has any of its qubits specified or not. If all of them are there, it would be similar to an Operation. If none of them are there, it would be similar to (most) Gates.

Earlier versions of pyquil provided first-class support for partial specification of qubits for each gate/operation. I ripped that out since people typically didn't use it (especially for NISQ algorithms) and in special cases you could use closures (at the python language level) for the same effect.

smitsanghavi commented 5 years ago

The original reason for going this route was to have the flexibility of calling control(GateX, my_control_qubits) to generate a ControlledGate where you can specify the qubits GateX uses (and also some more controls) later. The assumption was that control qubits might be used differently than "regular" qubits and having an option to pre-specify some controls without being asked to resolve the underlying Gate to an Operation might come in handy.

But if in the subsequent months no such use case has shown up, cleaning up the additional complexity is probably a good idea.