Restrict what you're allowed to do with a `Soquet` during bloq building
When you're authoring a bloq, you define a method build_composite_bloq(self, bb: BloqBuilder, ctrl, x, ...). The qualtran system will call this method suppling the bb: BloqBuilder argument as well as keyword arguments mapping register names (i.e. quantum argument names) gleaned from the bloq's signature to objects representing quantum variables. The bloq author can call quantum subroutines (i.e. other bloqs) on the quantum variables, and must return a dictionary mapping register names (i.e. quantum return value names) to the final quantum variable handles.
These "objects representing quantum variables" are either a Soquet object or an np.ndarray thereof. But the bloq author really shouldn't concern themselves with that:
- the system creates
Soquetobjects. The user (bloq author) should never be instantiating newSoquetobjects. - the
Soquet.binstandSoquet.idxattributes are completely inappropriate to access during bloq authoring and should be considered internal bookkeeping details. - Bloq authoring shouldn't rely on equality or hashing of soquet objects.
-
Soquet.reg.dtypeis used sometimes during bloq authoring with generic data types. It's the case that the data type of a given soquet should always be able to be figured out from the bloq class attributes; but it seems morally ok to access a quantum variables data type and this shows up some places.
I'd like to move towards deprecating these abilities specifically during bloq building.
Note: Qualtran developers, particularly those developers who are doing something fancy with a finalized, immutable CompositeBloq subroutines must and should use the soquet attributes, equality, and hashability. Ideally, these protocols shouldn't be instantiating Soquet objects directly but in practice that seems to happen.
Curious if you've considered having Soquets be member attributes on Bloqs instead of passing them in through the builders. For Cirq I spent a bunch of time looking into a way to reduce the overlap that exists in many cases between gates and operations, basically could we make it so that Operation just a dumb dataclass container with a gate, qubits, and tags, and disallowed SpecializedOperation subclasses? Where I landed was, yes we could, but it's probably not worth it. https://github.com/quantumlib/Cirq/issues/7465#issuecomment-3264354225. In principle it sounds right, but in practice it gets cumbersome, because almost everything you can do with a gate requires knowing the qubits anyway. So ultimately I ended up concluding that the best approach in an ideal world would be to go the opposite direction: to eliminate the operation layer entirely and just add qubit fields directly to the gates. Too late to make that big of a change to cirq though.
Here if they were members, you could also create a @bloq decorator that auto-generates the signature method implementation. It could check other things you might want to ensure too, like that the class is an attrs class so that replace is guaranteed to work on all bloqs (which, at least in cirq, would've been huge, as it'd have allowed tags to be a regular field on the base class rather than a whole wrapper layer with the bugs and usability problems it causes), etc.
Anyway, just figured I'd ask.
(Note this is somewhat tangential to the issue of what Bloqs should be able to do with a Soquet, but I didn't want to create a whole new issue for it.)
There are some other SDKs that don't have the Operation/Gate distinction, but I generally think it's a good one. It's particularly important for Qualtran because we rely a lot on caching properties of Bloq objects.
We don't have a strict analogue of cirq.Operation in Qualtran because our compute graph ("circuit") doesn't care about absolute qubit memory addresses. The closest thing is the return value from CompositeBloq.iter_bloqnections which is a three-tuple of the bloq instance, its incoming connections, and its outgoing connections; and isn't interacted with during normal usage of Qualtran. (You have to wrap your head around it if you're doing fancy library development)
because almost everything you can do with a gate requires knowing the qubits anyway
in qualtran, this would be "almost everything you can do with a gate requires knowing the signature", which is indeed the only required property of a Bloq and is independent of the gate's place within a larger circuit