Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user choice between U3 or GPI2 as single-qubit native gate #1095

Merged
merged 12 commits into from
Nov 27, 2023
11 changes: 5 additions & 6 deletions doc/source/code-examples/advancedexamples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2011,10 +2011,9 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
from qibo import gates
from qibo.models import Circuit
from qibo.transpiler.pipeline import Passes, assert_transpiling
from qibo.transpiler.abstract import NativeType
from qibo.transpiler.optimizer import Preprocessing
from qibo.transpiler.router import ShortestPaths
from qibo.transpiler.unroller import NativeGates
from qibo.transpiler.unroller import Unroller, NativeGates
from qibo.transpiler.placer import Random

# Define connectivity as nx.Graph
Expand All @@ -2040,10 +2039,10 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
# Routing step
custom_passes.append(ShortestPaths(connectivity=star_connectivity()))
# Gate decomposition step
custom_passes.append(NativeGates(two_qubit_natives=NativeType.iSWAP))
custom_passes.append(Unroller(native_gates=NativeGates.default()))

# Define the general pipeline
custom_pipeline = Passes(custom_passes, connectivity=star_connectivity(), native_gates=NativeType.iSWAP)
custom_pipeline = Passes(custom_passes, connectivity=star_connectivity(), native_gates=NativeGates.default())

# Call the transpiler pipeline on the circuit
transpiled_circ, final_layout = custom_pipeline(circuit)
Expand All @@ -2057,10 +2056,10 @@ Multiple transpilation steps can be implemented using the :class:`qibo.transpile
connectivity=star_connectivity(),
initial_layout=initial_layout,
final_layout=final_layout,
native_gates=NativeType.iSWAP
native_gates=NativeGates.default()
)

In this case circuits will first be transpiled to respect the 5-qubit star connectivity, with qubit 2 as the middle qubit. This will potentially add some SWAP gates.
Then all gates will be converted to native. The :class:`qibo.transpiler.unroller.NativeGates` transpiler used in this example assumes Z, RZ, GPI2 or U3 as
Then all gates will be converted to native. The :class:`qibo.transpiler.unroller.Unroller` transpiler used in this example assumes Z, RZ, GPI2 or U3 as
the single-qubit native gates, and supports CZ and iSWAP as two-qubit natives. In this case we restricted the two-qubit gate set to CZ only.
The final_layout contains the final logical-physical qubit mapping.
66 changes: 1 addition & 65 deletions src/qibo/transpiler/abstract.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,11 @@
from abc import ABC, abstractmethod
from enum import Flag, auto
from typing import Tuple

import networkx as nx

from qibo import gates
from qibo.config import raise_error
from qibo.models import Circuit


class NativeType(Flag):
"""Define available types of native gates.

Should have the same names with qibo gates.
"""

M = auto()
Z = auto()
RZ = auto()
GPI2 = auto()
CZ = auto()
iSWAP = auto()

@classmethod
def from_gate(cls, gate: gates.Gate):
try:
return getattr(cls, gate.__class__.__name__)
except AttributeError:
raise ValueError(f"Gate {gate} cannot be used as native.")


class Placer(ABC):
@abstractmethod
def __init__(self, connectivity: nx.Graph, *args):
Expand Down Expand Up @@ -72,51 +48,11 @@ class Optimizer(ABC):

@abstractmethod
def __call__(self, circuit: Circuit, *args) -> Circuit:
"""Find initial qubit mapping
"""Optimize transpiled circuit.

Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be optimized

Returns:
(:class:`qibo.models.circuit.Circuit`): circuit with optimized number of gates.
"""


class Unroller(ABC):
@abstractmethod
def __init__(self, native_gates: NativeType, *args):
"""An unroller decomposes gates into native gates."""

@abstractmethod
def __call__(self, circuit: Circuit, *args) -> Circuit:
"""Find initial qubit mapping

Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be optimized

Returns:
(:class:`qibo.models.circuit.Circuit`): circuit with native gates.
"""


def _find_gates_qubits_pairs(circuit: Circuit):
"""Translate qibo circuit into a list of pairs of qubits to be used by the router and placer.

Args:
circuit (:class:`qibo.models.circuit.Circuit`): circuit to be transpiled.

Returns:
(list): list containing qubits targeted by two qubit gates.
"""
translated_circuit = []
for gate in circuit.queue:
if isinstance(gate, gates.M):
pass
elif len(gate.qubits) == 2:
translated_circuit.append(sorted(gate.qubits))
elif len(gate.qubits) >= 3:
raise_error(
ValueError, "Gates targeting more than 2 qubits are not supported"
)

return translated_circuit
Loading