Skip to content

Conversation

mpharrigan
Copy link
Collaborator

We use the adapter pattern for adapting cirq and qualtran (bloq) obejcts, namely BloqAsCirqGate and CirqGateAsBloq. This PR does not modify qualtran.GateWithRegisters, which acts simultaneously as a cirq gate and qualtran bloq.

BloqAsCirqGate is now only a cirq.Gate.

This PR removes the signature and on_registers methods from BloqAsCirqGate(cirq.Gate). These methods are bloq-y and one shouldn't rely on them being available on something that purports to be a cirq gate.

BloqAsCirqGate also learns a new _has_unitary_ implementation, which fixes #1570. This fix was revealed when I encountered a related bug while writing this PR: one of the unit tests started taking a long (indefinite) time; which was again traced to cirq.Gate.controlled_by trying to validate that the gate was unitary.

CirqGateAsBloq is now only a Bloq.

This PR removes the GateWithRegisters(Bloq, cirq.Gate) functionality from the adapter. Only the bloq API is available on CirqGateAsBloq (so things like _unitary_, diagram info, ... are removed).

The functionality for CirqGateAsBloq is (still) contained in CirqGateAsBloqBase which can be used to bootstrap bloq definitions.

@mpharrigan mpharrigan requested a review from tanujkhattar March 26, 2025 00:12
@mpharrigan mpharrigan added this to the v1.0 milestone Mar 26, 2025
cbloq = bb.finalize(ctrl=ctrl, target=target)
target = bb.add(ZeroState())
q = [*ctrl, target]
c0, c1, target = bb.add(CirqGateAsBloq(and_gate), q=q)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a backwards incompatible change? The CirqGateAsBloq doesn't preserve the signature anymore if the underlying gate is a GateWithRegisters ?

In theory, this should be fine since GateWithRegisters are bloqs so we should use them without wrapping in CirqGateAsBloq, but I'm nervous that this might break stuff in the interop. The tests are passing so that's a good indication, but have you looked into any potential consequence of this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way to be full proof could be to raise an error if a user tries to wrap a GateWithRegisters into a CirqGateAsBloq (or any other object that satisfies isinstance(gate, Bloq)).

I don't like the current behavior where it silently works, but does the wrong thing. It's better to explicitly raise an error if we don't want / expect users to wrap bloq objects in this wrapper

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can add some error checking since this changes the behavior of using CirqGateAsBloq with a GateWithRegisters.

It was on purpose to make CirqGateAsBloq only use the cirq.Gate API, which doesn't have a notion of signatures. If we wanted to preserve the "special casing", I would (theoretically) argue for a different adapter: GateWithRegistersAsBloq... but this is redundant :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, I don't know if an error is appropriate: since GateWithRegisters is a cirq.Gate, you should be able to wrap it -- but it will treat it as a cirq gate. Maybe I'll emit a warning?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't silently fail anyways: if you were wrapping a sided GateWithRegisters with CirqGateAsBloq, the change will change the signature; which will raise an error when you're trying to wire it up.

And of course the fix is simple: remove the adapter! I've added a warning

Copy link
Collaborator

@tanujkhattar tanujkhattar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main feedback is to explicitly raise an error if CirqGateAsBloq is passed a Bloq object, instead of silently ignoring the LEFT / RIGHT registers and making everything a THRU register.

@mpharrigan
Copy link
Collaborator Author

This PR triggers #1336

@mpharrigan
Copy link
Collaborator Author

I'm going to revert the part of BloqAsCirqGate._unitary_ changes that forces the tensor_contract path

@mpharrigan
Copy link
Collaborator Author

pytest time back to normal (lower than normal?)

@mpharrigan mpharrigan merged commit 7a4c037 into quantumlib:main Apr 5, 2025
8 checks passed
wjhuggins pushed a commit to wjhuggins/Qualtran that referenced this pull request May 31, 2025
* strict BloqAsCirqGate and CirqGateAsBloq

* fixy

* Warn when wrapping a bloq

* let cirq handle _unitary_ still
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] TextbookQPE does not decompose successfully
2 participants