Source code for graphix.instruction
"""Instruction classes."""
from __future__ import annotations
import enum
import math
from dataclasses import dataclass, field
from enum import Enum
from typing import ClassVar, Literal, SupportsFloat
from graphix import utils
from graphix.fundamentals import Plane
# Ruff suggests to move this import to a type-checking block, but dataclass requires it here
from graphix.parameter import ExpressionOrFloat # noqa: TC001
from graphix.pretty_print import OutputFormat, angle_to_str
from graphix.repr_mixins import DataclassReprMixin
def repr_angle(angle: ExpressionOrFloat) -> str:
"""
Return the representation string of an angle in radians.
This is used for pretty-printing instructions with `angle` parameters.
Delegates to :func:`pretty_print.angle_to_str`.
"""
# Non-float-supporting objects are returned as-is
if not isinstance(angle, SupportsFloat):
return str(angle)
# Convert to float, express in π units, and format in ASCII/plain mode
pi_units = float(angle) / math.pi
return angle_to_str(pi_units, OutputFormat.ASCII)
[docs]
class InstructionKind(Enum):
"""Tag for instruction kind."""
CCX = enum.auto()
RZZ = enum.auto()
CNOT = enum.auto()
SWAP = enum.auto()
H = enum.auto()
S = enum.auto()
X = enum.auto()
Y = enum.auto()
Z = enum.auto()
I = enum.auto()
M = enum.auto()
RX = enum.auto()
RY = enum.auto()
RZ = enum.auto()
# The two following instructions are used internally by the transpiler
_XC = enum.auto()
_ZC = enum.auto()
class _KindChecker:
"""Enforce tag field declaration."""
def __init_subclass__(cls) -> None:
"""Validate that subclasses define the ``kind`` attribute."""
super().__init_subclass__()
utils.check_kind(cls, {"InstructionKind": InstructionKind, "Plane": Plane})
@dataclass(repr=False)
class CCX(_KindChecker, DataclassReprMixin):
"""Toffoli circuit instruction."""
target: int
controls: tuple[int, int]
kind: ClassVar[Literal[InstructionKind.CCX]] = field(default=InstructionKind.CCX, init=False)
@dataclass(repr=False)
class RZZ(_KindChecker, DataclassReprMixin):
"""RZZ circuit instruction."""
target: int
control: int
angle: ExpressionOrFloat = field(metadata={"repr": repr_angle})
# FIXME: Remove `| None` from `meas_index`
# - `None` makes codes messy/type-unsafe
meas_index: int | None = None
kind: ClassVar[Literal[InstructionKind.RZZ]] = field(default=InstructionKind.RZZ, init=False)
[docs]
@dataclass(repr=False)
class CNOT(_KindChecker, DataclassReprMixin):
"""CNOT circuit instruction."""
target: int
control: int
kind: ClassVar[Literal[InstructionKind.CNOT]] = field(default=InstructionKind.CNOT, init=False)
[docs]
@dataclass(repr=False)
class SWAP(_KindChecker, DataclassReprMixin):
"""SWAP circuit instruction."""
targets: tuple[int, int]
kind: ClassVar[Literal[InstructionKind.SWAP]] = field(default=InstructionKind.SWAP, init=False)
[docs]
@dataclass(repr=False)
class H(_KindChecker, DataclassReprMixin):
"""H circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.H]] = field(default=InstructionKind.H, init=False)
[docs]
@dataclass(repr=False)
class S(_KindChecker, DataclassReprMixin):
"""S circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.S]] = field(default=InstructionKind.S, init=False)
[docs]
@dataclass(repr=False)
class X(_KindChecker, DataclassReprMixin):
"""X circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.X]] = field(default=InstructionKind.X, init=False)
[docs]
@dataclass(repr=False)
class Y(_KindChecker, DataclassReprMixin):
"""Y circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.Y]] = field(default=InstructionKind.Y, init=False)
[docs]
@dataclass(repr=False)
class Z(_KindChecker, DataclassReprMixin):
"""Z circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.Z]] = field(default=InstructionKind.Z, init=False)
@dataclass(repr=False)
class I(_KindChecker, DataclassReprMixin):
"""I circuit instruction."""
target: int
kind: ClassVar[Literal[InstructionKind.I]] = field(default=InstructionKind.I, init=False)
[docs]
@dataclass(repr=False)
class M(_KindChecker, DataclassReprMixin):
"""M circuit instruction."""
target: int
plane: Plane
angle: ExpressionOrFloat = field(metadata={"repr": repr_angle})
kind: ClassVar[Literal[InstructionKind.M]] = field(default=InstructionKind.M, init=False)
[docs]
@dataclass(repr=False)
class RX(_KindChecker, DataclassReprMixin):
"""X rotation circuit instruction."""
target: int
angle: ExpressionOrFloat = field(metadata={"repr": repr_angle})
meas_index: int | None = None
kind: ClassVar[Literal[InstructionKind.RX]] = field(default=InstructionKind.RX, init=False)
[docs]
@dataclass(repr=False)
class RY(_KindChecker, DataclassReprMixin):
"""Y rotation circuit instruction."""
target: int
angle: ExpressionOrFloat = field(metadata={"repr": repr_angle})
meas_index: int | None = None
kind: ClassVar[Literal[InstructionKind.RY]] = field(default=InstructionKind.RY, init=False)
[docs]
@dataclass(repr=False)
class RZ(_KindChecker, DataclassReprMixin):
"""Z rotation circuit instruction."""
target: int
angle: ExpressionOrFloat = field(metadata={"repr": repr_angle})
meas_index: int | None = None
kind: ClassVar[Literal[InstructionKind.RZ]] = field(default=InstructionKind.RZ, init=False)
@dataclass
class _XC(_KindChecker):
"""X correction circuit instruction. Used internally by the transpiler."""
target: int
domain: set[int]
kind: ClassVar[Literal[InstructionKind._XC]] = field(default=InstructionKind._XC, init=False)
@dataclass
class _ZC(_KindChecker):
"""Z correction circuit instruction. Used internally by the transpiler."""
target: int
domain: set[int]
kind: ClassVar[Literal[InstructionKind._ZC]] = field(default=InstructionKind._ZC, init=False)
Instruction = CCX | RZZ | CNOT | SWAP | H | S | X | Y | Z | I | M | RX | RY | RZ | _XC | _ZC