Skip to content

Commit

Permalink
Merge pull request #1422 from qiboteam/unroller_cnot
Browse files Browse the repository at this point in the history
Add `gates.CNOT` as a native gate in gate decomposition
  • Loading branch information
BrunoLiegiBastonLiegi authored Aug 28, 2024
2 parents 386fe25 + 3281871 commit ecbd16d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
6 changes: 6 additions & 0 deletions src/qibo/transpiler/decompositions.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ def _u3_to_gpi2(t, p, l):
lambda gate: two_qubit_decomposition(0, 1, gate.matrix(backend), backend=backend),
)

# temporary CNOT decompositions for CNOT, CZ, SWAP
cnot_dec_temp = GateDecompositions()
cnot_dec_temp.add(gates.CNOT, [gates.CNOT(0, 1)])
cnot_dec_temp.add(gates.CZ, [gates.H(1), gates.CNOT(0, 1), gates.H(1)])
cnot_dec_temp.add(gates.SWAP, [gates.CNOT(0, 1), gates.CNOT(1, 0), gates.CNOT(0, 1)])

# register other optimized gate decompositions
opt_dec = GateDecompositions()
opt_dec.add(
Expand Down
20 changes: 18 additions & 2 deletions src/qibo/transpiler/unroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
from qibo.config import raise_error
from qibo.models import Circuit
from qibo.transpiler._exceptions import DecompositionError
from qibo.transpiler.decompositions import cz_dec, gpi2_dec, iswap_dec, opt_dec, u3_dec
from qibo.transpiler.decompositions import (
cnot_dec_temp,
cz_dec,
gpi2_dec,
iswap_dec,
opt_dec,
u3_dec,
)


class NativeGates(Flag):
Expand All @@ -22,6 +29,7 @@ class NativeGates(Flag):
- :class:`qibo.gates.gates.U3`
- :class:`qibo.gates.gates.CZ`
- :class:`qibo.gates.gates.iSWAP`
- :class:`qibo.gates.gates.CNOT`
"""

I = auto()
Expand All @@ -32,6 +40,7 @@ class NativeGates(Flag):
U3 = auto()
CZ = auto()
iSWAP = auto()
CNOT = auto() # For testing purposes

@classmethod
def default(cls):
Expand Down Expand Up @@ -240,6 +249,13 @@ def _translate_two_qubit_gates(gate: gates.Gate, native_gates: NativeGates):
iswap_decomposed.append(g_translated)
return iswap_decomposed

# For testing purposes
# No CZ, iSWAP gates in the native gate set
# Decompose CNOT, CZ, SWAP gates into CNOT gates
if native_gates & NativeGates.CNOT:
return cnot_dec_temp(gate)

raise_error(
DecompositionError, "Use only CZ and/or iSWAP as native gates"
DecompositionError,
"Use only CZ and/or iSWAP as native gates. CNOT is allowed in circuits where the two-qubit gates are limited to CZ, CNOT, and SWAP.",
) # pragma: no cover
33 changes: 33 additions & 0 deletions tests/test_transpiler_unroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,36 @@ def test_measurements_non_comp_basis():
assert isinstance(transpiled_circuit.queue[2], gates.M)
# After transpiling the measurement gate should be in the computational basis
assert transpiled_circuit.queue[2].basis == []


def test_temp_cnot_decomposition():
from qibo.transpiler.pipeline import Passes

circ = Circuit(2)
circ.add(gates.H(0))
circ.add(gates.CNOT(0, 1))
circ.add(gates.SWAP(0, 1))
circ.add(gates.CZ(0, 1))
circ.add(gates.M(0, 1))

glist = [gates.GPI2, gates.RZ, gates.Z, gates.M, gates.CNOT]
native_gates = NativeGates(0).from_gatelist(glist)

custom_pipeline = Passes([Unroller(native_gates=native_gates)])
transpiled_circuit, _ = custom_pipeline(circ)

# H
assert transpiled_circuit.queue[0].name == "z"
assert transpiled_circuit.queue[1].name == "gpi2"
# CNOT
assert transpiled_circuit.queue[2].name == "cx"
# SWAP
assert transpiled_circuit.queue[3].name == "cx"
assert transpiled_circuit.queue[4].name == "cx"
assert transpiled_circuit.queue[5].name == "cx"
# CZ
assert transpiled_circuit.queue[6].name == "z"
assert transpiled_circuit.queue[7].name == "gpi2"
assert transpiled_circuit.queue[8].name == "cx"
assert transpiled_circuit.queue[9].name == "z"
assert transpiled_circuit.queue[10].name == "gpi2"

0 comments on commit ecbd16d

Please sign in to comment.