Skip to content

Commit

Permalink
fix: Simplify missing gates handling
Browse files Browse the repository at this point in the history
  • Loading branch information
alecandido committed Aug 17, 2024
1 parent 5e3593b commit d7a372b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
16 changes: 6 additions & 10 deletions src/qibolab/compilers/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,16 @@ def identity_rule(gate: Gate, natives: SingleQubitNatives) -> PulseSequence:

def gpi2_rule(gate: Gate, natives: SingleQubitNatives) -> PulseSequence:
"""Rule for GPI2."""
assert natives.RX is not None
return natives.RX.create_sequence(theta=np.pi / 2, phi=gate.parameters[0])
return natives.ensure("RX").create_sequence(theta=np.pi / 2, phi=gate.parameters[0])


def gpi_rule(gate: Gate, qubit: Qubit) -> PulseSequence:
def gpi_rule(gate: Gate, natives: SingleQubitNatives) -> PulseSequence:
"""Rule for GPI."""
# the following definition has a global phase difference compare to
# to the matrix representation. See
# https://github.com/qiboteam/qibolab/pull/804#pullrequestreview-1890205509
# for more detail.
return qubit.RX.create_sequence(theta=np.pi, phi=gate.parameters[0])
return natives.ensure("RX").create_sequence(theta=np.pi, phi=gate.parameters[0])


def cz_rule(gate: Gate, natives: TwoQubitNatives) -> PulseSequence:
Expand All @@ -49,22 +48,19 @@ def cz_rule(gate: Gate, natives: TwoQubitNatives) -> PulseSequence:
Applying the CZ gate may involve sending pulses on qubits that the
gate is not directly acting on.
"""
assert natives.CZ is not None
return natives.CZ.create_sequence()
return natives.ensure("CZ").create_sequence()


def cnot_rule(gate: Gate, natives: TwoQubitNatives) -> PulseSequence:
"""CNOT applied as defined in the platform runcard."""
assert natives.CNOT is not None
return natives.CNOT.create_sequence()
return natives.ensure("CNOT").create_sequence()


def measurement_rule(gate: Gate, natives: list[SingleQubitNatives]) -> PulseSequence:
"""Measurement gate applied using the platform readout pulse."""
seq = PulseSequence()
for qubit in natives:
assert qubit.MZ is not None
seq.concatenate(qubit.MZ.create_sequence())
seq.concatenate(qubit.ensure("MZ").create_sequence())
return seq


Expand Down
30 changes: 26 additions & 4 deletions src/qibolab/native.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from abc import ABC, abstractmethod
from typing import Annotated, Optional

import numpy as np
Expand All @@ -14,7 +15,13 @@ def _normalize_angles(theta, phi):
return theta, phi


class RxyFactory(PulseSequence):
class Native(ABC, PulseSequence):
@abstractmethod
def create_sequence(self, *args, **kwargs) -> PulseSequence:
"""Create a sequence for single-qubit rotation."""


class RxyFactory(Native):
"""Factory for pulse sequences that generate single-qubit rotations around
an axis in xy plane.
Expand Down Expand Up @@ -66,14 +73,29 @@ def create_sequence(self, theta: float = np.pi, phi: float = 0.0) -> PulseSequen
)


class FixedSequenceFactory(PulseSequence):
class FixedSequenceFactory(Native):
"""Simple factory for a fixed arbitrary sequence."""

def create_sequence(self) -> PulseSequence:
return self.copy()


class SingleQubitNatives(Model):
class MissingNative(RuntimeError):
"""Missing native gate."""

def __init__(self, gate: str):
super().__init__(f"Native gate definition not found, for gate {gate}")


class NativeContainer(Model):
def ensure(self, name: str) -> Native:
value = getattr(self, name)
if value is None:
raise MissingNative(value)
return value


class SingleQubitNatives(NativeContainer):
"""Container with the native single-qubit gates acting on a specific
qubit."""

Expand All @@ -87,7 +109,7 @@ class SingleQubitNatives(Model):
"""Pulse to activate coupler."""


class TwoQubitNatives(Model):
class TwoQubitNatives(NativeContainer):
"""Container with the native two-qubit gates acting on a specific pair of
qubits."""

Expand Down

0 comments on commit d7a372b

Please sign in to comment.