Open ncrubin opened 3 years ago
The native gate that we calibrate is fsim(pi/4, 0) which in our sign convention corresponds to sqrt(iswap)^{-1}. That's probably why the optimizer was implemented that way. Note, however, that sqrt(iswap)^{-1} is implemented internally as a block with physical Z rotations on each qubit for phase matching, followed by the entangler. The phase matching is required because the qubits do not idle at the same frequency, and sqrt(iswap) does not commute with Z so we can't use virtual Zs for matching as we do for CZ or iswap. We do this gate as a block so that it can be self-contained, otherwise we'd have to require users to prefix every sqrt(iswap) gate in their circuits with special "phase matching physical Z" gates, which would be very unergonomic, or know the qubit frequencies and gate timings and account for the phase mismatch terms manually, which would be even worse.
As you note, sqrt(iswap) can be obtained from sqrt(iswap)^{-1} by adding Z gates on one qubit. We do this internally with virtual Z gates, so they don't change the gate time. The leading Z gets absorbed into the physical Z matching gates, and the trailing Z just propagates forward through the circuit as we compile, but doesn't take up any time.
So, sqrt(iswap)^{+/-1} both include physical Z gates for phase matching, and both take the same amount of time to run. The code prefers sqrt(iswap)^{-1} for reasons of history and sign convention, but this could be changed.
I should also mention that while we default to using virtual Z gates for phase matching on entanglers where possible (e.g. for CZ and iswap), it is now possible to tag entangling gates with cirq.google.PhysicalZTag()
to specify that physical Z matching rotations should be used instead (see https://github.com/quantumlib/Cirq/pull/3862). You can also tag sqrt(iswap) in this way, but it makes no difference since that's already the default behavior.
@ncrubin Given @maffoo's explanation, can we close this or is there something else to do here?
It would be nice to articulate maffoo's very informative answer somewhere in the docs. Also I recall @mrwojtek had some issues with the Floquet code not working with sqrt(iswap) but correctly working for sqrt(iswap)^{-1}? Or do I have that the other way around?
@ncrubin I have checked the behavior of sqrt(iswap) and sqrt(iswap)^{-1} in Floquet code and so far they seem to be supported correctly. I suspect the problem you observed might have been caused by something else but to check that I would need to see the code that you are using in your experiment as well as your circuits with sqrt(iswap).
Cool cool. I just wanted to make sure I am communicating the correct information. It sounds like both sqrt(iswap) and sqrt(iswap)^{-1} are formally in our gate set. But what happens if a user uses a physical Z tag for Rz(pi) pulses to change a sqrt(iswap) to sqrt(iswap)^{-1}. Did they just make the circuit needlessly longer?
But what happens if a user uses a physical Z tag for Rz(pi) pulses to change a sqrt(iswap) to sqrt(iswap)^{-1}. Did they just make the circuit needlessly longer?
Yes.
Good to know. In here, it is clearly suggested that SQRT_ISWAP_INV and SQRT_ISWAP are native. The docs only indicate iswap**-0.5 which might be a source of confusion.
Marked it as a kind/doc item.
optimize_for_sycamore returns sqrt(iswap)^{-1}. Is this a supported gate or is QuantumEngine secretly converting this to Rz sqrt(iswap) Rz without telling the user?
considering we have Physical Rz and virtual Rz there should be no gratuitous transformation of gates coming from users