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

Add ECR/iSwap to list of gates handled by `Clifford.from_circuit` #9582

Closed kdk closed 1 year ago

kdk commented 1 year ago

What should we add?

Clifford.from_circuit has a list of 1- and 2-qubit Cliffords that it knows how to handle via updating the tableau directly. https://github.com/Qiskit/qiskit-terra/blob/1fb00e628a73f960980648cf9c4db0dfecc936ca/qiskit/quantum_info/operators/symplectic/clifford_circuits.py#L331

This list currently doesn't include some Clifford gates from the standard library like ECR and iSwap. For iSwap, this is not a problem because it's .definition is all Clifford, but ECR is defined in terms of RZX and so can't be converted directly. This partially covered by #9475 but requires falling back to the matrix form to reconstruct the tableau.

ShellyGarion commented 1 year ago

There are two approaches here:

The first is to add ecr to the clifford circuits _BASIS_2q using the following Clifford table:

[[ True  True  True False  True]
 [False  True False False False]
 [False False  True False  True]
 [False  True  True  True False]]

The second is to add an equivalent definition of the ECRGate() to the equivalence library (assuming that the Clifford class will handle equivalent definitions):

qc = QuantumCircuit(2)
qc.h(1)
qc.s(0)
qc.sdg(1)
qc.h(1)
qc.cx(0, 1)
qc.x(0)
qc.x(1)
print (qc)
print (Clifford(qc))
assert (Operator(qc).equiv(Operator(ECRGate())))
ShellyGarion commented 1 year ago

Note that in the circuit library there are some Clifford gates that do not appear in the clifford_circuits.py file, but since their definition includes only Clifford gates, then they are converted automatically into Cliffords. These gates include:

CYGate()
iSWAPGate()
SXGate()
SXdgGate()

Do we want to add them to clifford_circuits.py ?

kdk commented 1 year ago

There are two approaches here:

The first is to add ecr to the clifford circuits _BASIS_2q using the following Clifford table:

...

The second is to add an equivalent definition of the ECRGate() to the equivalence library (assuming that the Clifford class will handle equivalent definitions):

...

These both seem viable to me. Having a Clifford-only definition in the equivalence library would be useful in general, since the only path from ECR to CX now requires to RZXs, which in turn will generate two CX gates. I don't think clifford_circuits.py currently checks the EquivalenceLibrary though, only Instruction.definition, though I don't see any reason why it couldn't.

Note that in the circuit library there are some Clifford gates that do not appear in the clifford_circuits.py file, but since their definition includes only Clifford gates, then they are converted automatically into Cliffords. These gates include:

...

Do we want to add them to clifford_circuits.py ?

Having them in clifford_circuits.py should be moderately faster, but I think having them there would be beneficial for completeness and to guard against the case that their definition changes in the future to something like a QASM-style definition that isn't expressed in terms of Cliffords.

kdk commented 1 year ago

Copying over context from @ShellyGarion 's comment on https://github.com/Qiskit/qiskit-terra/pull/9475#issuecomment-1431014041 that we should discuss here:

Gates that are Cliffords only for certain parameters (e.g. an integer multiplication of pi or pi/2). Perhaps they can also be added to the file clifford_circuits.py, defining new lists of gates: _BASIS_1Q_with_params and _BASIS_2Q_with_params, and check both the gate name and the gate params here.

        RXGate(theta=np.pi / 2),
        RYGate(theta=np.pi / 2),
        RZGate(phi=np.pi / 2),
        CPhaseGate(theta=np.pi),
        CRXGate(theta=np.pi),
        CRYGate(theta=np.pi),
        CRZGate(theta=np.pi),
        RXXGate(theta=np.pi / 2),
        RYYGate(theta=np.pi / 2),
        RZZGate(theta=np.pi / 2),
        RZXGate(theta=np.pi / 2),
        XXMinusYYGate(theta=np.pi),
        XXPlusYYGate(theta=-np.pi),
itoko commented 1 year ago

There seems several possible approaches for performance improvement of Clifford.from_circuit: 1) Add more _append_* functions 2) Add a special EquivalenceLibrary for Clifford gates and use it for decomposition instead of definition (keeping _append_* functions minimal) 3) Implement Clifford.from_matrix in Rust (if it gets 10x faster, comparative with other approaches in Python)

ShellyGarion commented 1 year ago

In #9623 I added all the Clifford gates that are currently in the circuit library to clifford_circuits.py directly using _append_* (this is important for completeness in case their definition will change in the future).

As for parametrized gates, that are Clifford only for certain parameters (usually for integer multiplications of pi or pi/2), adding more _append_* functions may not so scalable. One approach is to use #9475 to recursively define the circuit using Clifford and U or Rz gates with appropriate angles. Another option is to define an EquivalenceLibrary for Cliffords, that can also include parametrized gates.