Qiskit / qiskit

Qiskit is an open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
https://www.ibm.com/quantum/qiskit
Apache License 2.0
4.86k stars 2.29k forks source link

Global phase gate #8236

Closed kevinsung closed 1 year ago

kevinsung commented 2 years ago

What should we add?

A gate that intruduces a global phase.

ewinston commented 2 years ago

This idea was brought up at least once before,

https://github.com/Qiskit/qiskit-terra/pull/1810

It would mean a significant change to how global phase is tracked which I'm not sure has a good justification over updating the global phase on the circuit.

kevinsung commented 2 years ago

The use case I have in mind is for writing subroutines that yield gates without having the circuit around. Something like

def quantum_fourier_transform(register: QuantumRegister) -> Iterator[tuple[Instruction, Sequence[Qubit]]]

If you appended these operations into a circuit, it's true that any global phase gates wouldn't have an observable effect. But if you then wanted to create a controlled version of that circuit, the global phase gates would matter.

jakelishman commented 2 years ago

I think since the issue Erick mentioned, there has been a significant change to how we handle global phase. The idea of a simple "global phase" gate that can be used in compound gate definitions sounds fairly convenient to me, for the reasons Kevin mentions above - when you control the gate onto a subset of the qubits, it's no longer a "global" phase, and it is convenient to be able to affect it in the same way as any other gate (OpenQASM 3 also takes this approach with the gphase instruction).

In theory we can just make a gate class whose definition is just QuantumCircuit(global_phase=params[0]), and acts on no qubits or clbits. In practice right now, there's a couple of implementation bugs (QuantumCircuit.to_gate() not accepting zero-qubit gates being one that I immediately found), but those are just little edge-case nonsense that we should fix anyway.

ewinston commented 2 years ago

It's currently possible to have a gate whose definition includes a global phase such that when it's controlled, that global (now relative) phase is taken into account.

The fact that they appear in OpenQASM 3 sounds like a good reason to include them, although I'm still somewhat worried about the tracking of phase. In that description it sounds like the gphase instruction adds to the phase of the containing scope. Currently when circuits are composed you can just look at two spots for the global phase. With this change it sounds like you would have to iterate through the circuit and recalculate it.

jakelishman commented 2 years ago

You don't really have to recalculate it - it all gets pulled in automatically by anything that walks the definitions, because it's all the exact same thing. At the end of the day, we're still encoding the global phase in the QuantumCircuit.global_phase attribute of some subobject, just like how regular gates are handled now. With the bug fixes of #8272, I tested it with an ad-hoc gate defined by:

import math
from qiskit import QuantumCircuit
phase = QuantumCircuit(global_phase=math.pi).to_gate()
qc = QuantumCircuit(2, 2)
qc.append(phase, [], [])

and it all works just fine. The global phase doesn't get pulled into qc's global_phase at this stage (we wouldn't expect it to), but it works entirely correctly if you do things like qc.control() (it turns it into a phase gate) or use quantum_info.Operator to get the matrix representation.

ewinston commented 2 years ago

If it's "tracked" how it is currently done through instruction definition that seems fine. Currently QuantumCircuit.global_phase represents the global phase of the circuit as represented. If any of the individual instructions in the circuit are transformed to another set of instructions, with a possible relative phase, that gets reflected up to the containing circuit at that time.