Skip to content

Simplify Operation design #7465

Open
@daxfohl

Description

@daxfohl

Is your design idea/issue related to a use case or problem? Please explain

There is a lot of redundancy between Gate and Operation for certain types of gate/operation pairs. It's maintenance overhead, unintuitive for new users, possibly degrades performance, and makes things like tagged operations hard to work with.

Describe your design idea/issue

I propose there should only be one Operation type (meaning, Operation is the implementation itself, not the interface to the "one implementation"). It should be a "final" class (or as close as you can get to it in Python), and roughly equivalent to what GateOperation is currently. Everything else should be a Gate.

This allows Operation to be a dataclass. This allows it to be immutable (frozen), but with the quality that tagging an operation is just a matter of calling replace on the tags field. You don't have to create a separate TaggedOperation class that wraps the an underlying operation, forwards all methods, and requires users to unwrap every time they need to check something on the original operation again.

The primary knock-on effects would be on

  • CircuitOperation: There's not currently a CircuitGate, but it would be fairly straightforward to create one, just replacing qubits with indices everywhere. Then Operation(circuit_gate, qubits) would be simulateable just like any other gate. I did a PoC of this in POC for CircuitGate #4725 a while back.
    • Important side note: this approach would also potentially allow for some perf improvements, as applying operations to the state space by index will be faster than dictionary lookups of Qid objects. In fact, I think if we do this, the approach could/should be extended to the whole circuit: just use indexes at the Circuit level, and you don't actually deal with Qids until you apply the circuit to a device. Pushing Qid out of the Circuit layer could have positive perf impact on both simulation and circuit construction. It would make annoyances in things like decomposition protocols (decompose vs decompose_with_qubits) and such go away, and eliminate the boilerplate q1, q2, q3 = qs = cirq.LineQubit.range(3) etc that begin each unit test.
  • ClassicallyControlledOperation: There's also no equivalent gate for this. The primary reason for that decision was that it needed to support classically controlled CircuitOperations. Once there are CircuitGates, creating a ClassicallyControlledGate class and removing ClassicallyControlledOperation should be straightforward.
  • PauliString (and related): I'm not so familiar with these, but I have to imagine there's some way to accommodate. Given there's a combinatorial class explosion around PS, Mutable PS, Dense PS, (proposed) Sparse PS, I hope removing a dimension from that might be more beneficial than detrimental.

This is obviously a big change (cirq 2.x, not 1.x). If there's not going to be a 2.x, this can probably be closed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/gatesgood part-time projectA meaty non-urgent issue with a substantial amount of work to be done.kind/design-issueA conversation around design

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions