"""Iceberg code extension."""
import functools
from hugr.ext import Extension, OpDef, TypeDef
from hugr.ops import ExtOp
from hugr.std.float import FLOAT_T
from hugr.std.int import int_t
from hugr.tys import BoundedNatArg, ExtType, FunctionType, Option
from tket_exts import measurement
from ._util import load_extension
_IDX_T = int_t(6)
_MEAS_T = measurement.measurement_t
[docs]
class IcebergTypesExtension:
"""Extension providing the Iceberg logical types."""
[docs]
def __call__(self) -> Extension:
"""Returns the Iceberg types extension."""
return load_extension("guppyft.iceberg.types")
@functools.cached_property
def iceberg_block_def(self) -> TypeDef:
"""An Iceberg code block.
This is the generic type definition. For the instantiated type, see
`iceberg_block`.
"""
return self().get_type("block")
[docs]
def iceberg_block(self, k: int) -> ExtType:
"""An Iceberg code block.
Args:
k: The number of logical qubits encoded in the block.
"""
return self.iceberg_block_def.instantiate([BoundedNatArg(k)])
@functools.cached_property
def iceberg_borrowed_block_def(self) -> TypeDef:
"""A borrowed Iceberg code block.
This is the generic type definition. For the instantiated type, see
`iceberg_borrowed_block`.
"""
return self().get_type("borrowed_block")
[docs]
def iceberg_borrowed_block(self, k: int) -> ExtType:
"""A borrowed Iceberg code block.
Args:
k: The number of logical qubits encoded in the original block.
"""
return self.iceberg_borrowed_block_def.instantiate([BoundedNatArg(k)])
@functools.cached_property
def iceberg_pre_block_def(self) -> TypeDef:
"""An Iceberg code pre-block.
This is the generic type definition. For the instantiated type, see
`iceberg_pre_block`.
"""
return self().get_type("pre_block")
[docs]
def iceberg_pre_block(self, k: int) -> ExtType:
"""An Iceberg code pre-block.
Args:
k: The number of logical qubits encoded in the block.
"""
return self.iceberg_pre_block_def.instantiate([BoundedNatArg(k)])
@functools.cached_property
def iceberg_qubit_def(self) -> TypeDef:
"""A "dynamic" logical qubit belonging to an unspecified block.
This is the generic type definition. For the instantiated type, see
`iceberg_qubit`.
"""
return self().get_type("qubit")
[docs]
def iceberg_qubit(self) -> ExtType:
"""A "dynamic" logical qubit belonging to an unspecified block."""
return self.iceberg_qubit_def.instantiate([])
_ICEBERG_TYPES = IcebergTypesExtension()
_DYNQ_T = _ICEBERG_TYPES.iceberg_qubit()
[docs]
class IcebergOpsExtension:
"""Extension providing the Iceberg logical operations."""
[docs]
def __call__(self) -> Extension:
"""Returns the Iceberg ops extension."""
return load_extension(
"guppyft.iceberg.ops", ["guppyft.std.types", "guppyft.iceberg.types"]
)
# x
@functools.cached_property
def x_def(self) -> OpDef:
"""Apply an X gate to one qubit.
This is the generic operation definition. For the instantiated operation, see
`x`."""
return self().get_op("x")
[docs]
def x(self, k: int) -> ExtOp:
"""Apply an X gate to one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# y
@functools.cached_property
def y_def(self) -> OpDef:
"""Apply a Y gate to one qubit.
This is the generic operation definition. For the instantiated operation, see
`y`."""
return self().get_op("y")
[docs]
def y(self, k: int) -> ExtOp:
"""Apply a Y gate to one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.y_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# z
@functools.cached_property
def z_def(self) -> OpDef:
"""Apply a Z gate to one qubit.
This is the generic operation definition. For the instantiated operation, see
`z`."""
return self().get_op("z")
[docs]
def z(self, k: int) -> ExtOp:
"""Apply a Z gate to one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# xx
@functools.cached_property
def xx_def(self) -> OpDef:
"""Apply an X gate to two qubits.
This is the generic operation definition. For the instantiated operation, see
`xx`."""
return self().get_op("xx")
[docs]
def xx(self, k: int) -> ExtOp:
"""Apply an X gate to two qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.xx_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T, _IDX_T], [block_type]),
)
# yy
@functools.cached_property
def yy_def(self) -> OpDef:
"""Apply a Y gate to two qubits.
This is the generic operation definition. For the instantiated operation, see
`yy`."""
return self().get_op("yy")
[docs]
def yy(self, k: int) -> ExtOp:
"""Apply a Y gate to two qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.yy_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T, _IDX_T], [block_type]),
)
# zz
@functools.cached_property
def zz_def(self) -> OpDef:
"""Apply a Z gate to two qubits.
This is the generic operation definition. For the instantiated operation, see
`zz`."""
return self().get_op("zz")
[docs]
def zz(self, k: int) -> ExtOp:
"""Apply a Z gate to two qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.zz_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T, _IDX_T], [block_type]),
)
# all_but_one_x
@functools.cached_property
def all_but_one_x_def(self) -> OpDef:
"""Apply an X gate to all but one qubit.
This is the generic operation definition. For the instantiated operation, see
`all_but_one_x`."""
return self().get_op("all_but_one_x")
[docs]
def all_but_one_x(self, k: int) -> ExtOp:
"""Apply an X gate to all but one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_but_one_x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# all_but_one_z
@functools.cached_property
def all_but_one_z_def(self) -> OpDef:
"""Apply a Z gate to all but one qubit.
This is the generic operation definition. For the instantiated operation, see
`all_but_one_z`."""
return self().get_op("all_but_one_z")
[docs]
def all_but_one_z(self, k: int) -> ExtOp:
"""Apply a Z gate to all but one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_but_one_z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# all_x
@functools.cached_property
def all_x_def(self) -> OpDef:
"""Apply an X gate to all qubits.
This is the generic operation definition. For the instantiated operation, see
`all_x`."""
return self().get_op("all_x")
[docs]
def all_x(self, k: int) -> ExtOp:
"""Apply an X gate to all qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type], [block_type]),
)
# all_y
@functools.cached_property
def all_y_def(self) -> OpDef:
"""Apply a Y gate to all qubits.
This is the generic operation definition. For the instantiated operation, see
`all_y`."""
return self().get_op("all_y")
[docs]
def all_y(self, k: int) -> ExtOp:
"""Apply a Y gate to all qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_y_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type], [block_type]),
)
# all_z
@functools.cached_property
def all_z_def(self) -> OpDef:
"""Apply a Z gate to all qubits.
This is the generic operation definition. For the instantiated operation, see
`all_z`."""
return self().get_op("all_z")
[docs]
def all_z(self, k: int) -> ExtOp:
"""Apply a Z gate to all qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type], [block_type]),
)
# x_with_all_but_one_z
@functools.cached_property
def x_with_all_but_one_z_def(self) -> OpDef:
"""Apply an X gate to one qubit and a Z to the rest.
This is the generic operation definition. For the instantiated operation, see
`x_with_all_but_one_z`."""
return self().get_op("x_with_all_but_one_z")
[docs]
def x_with_all_but_one_z(self, k: int) -> ExtOp:
"""Apply an X gate to one qubit and a Z to the rest.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.x_with_all_but_one_z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# z_with_all_but_one_x
@functools.cached_property
def z_with_all_but_one_x_def(self) -> OpDef:
"""Apply a Z gate to one qubit and an X to the rest.
This is the generic operation definition. For the instantiated operation, see
`z_with_all_but_one_x`."""
return self().get_op("z_with_all_but_one_x")
[docs]
def z_with_all_but_one_x(self, k: int) -> ExtOp:
"""Apply a Z gate to one qubit and an X to the rest.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.z_with_all_but_one_x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# fan_out
@functools.cached_property
def fan_out_def(self) -> OpDef:
"""Fan out from one qubit to the rest.
This is the generic operation definition. For the instantiated operation, see
`fan_out`."""
return self().get_op("fan_out")
[docs]
def fan_out(self, k: int) -> ExtOp:
"""Fan out from one qubit to the rest.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.fan_out_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# fan_in
@functools.cached_property
def fan_in_def(self) -> OpDef:
"""Fan in to one qubit from the rest.
This is the generic operation definition. For the instantiated operation, see
`fan_in`."""
return self().get_op("fan_in")
[docs]
def fan_in(self, k: int) -> ExtOp:
"""Fan in to one qubit from the rest.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.fan_in_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T], [block_type]),
)
# rx
@functools.cached_property
def rx_def(self) -> OpDef:
"""Apply an Rx gate to one qubit.
This is the generic operation definition. For the instantiated operation, see
`rx`."""
return self().get_op("rx")
[docs]
def rx(self, k: int) -> ExtOp:
"""Apply an Rx gate to one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.rx_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# rz
@functools.cached_property
def rz_def(self) -> OpDef:
"""Apply an Rz gate to one qubit.
This is the generic operation definition. For the instantiated operation, see
`rz`."""
return self().get_op("rz")
[docs]
def rz(self, k: int) -> ExtOp:
"""Apply an Rz gate to one qubit.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.rz_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# pauli_exp_all_x
@functools.cached_property
def pauli_exp_all_x_def(self) -> OpDef:
r"""Apply the logical all-X Pauli exponential.
.. math::
\exp(-i \theta X^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_x``.
"""
return self().get_op("pauli_exp_all_x")
[docs]
def pauli_exp_all_x(self, k: int) -> ExtOp:
r"""Apply the logical all-X Pauli exponential.
.. math::
\exp(-i \theta X^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, FLOAT_T], [block_type]),
)
# pauli_exp_all_y
@functools.cached_property
def pauli_exp_all_y_def(self) -> OpDef:
r"""Apply the logical all-Y Pauli exponential.
.. math::
\exp(-i \theta Y^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_y``.
"""
return self().get_op("pauli_exp_all_y")
[docs]
def pauli_exp_all_y(self, k: int) -> ExtOp:
r"""Apply the logical all-Y Pauli exponential.
.. math::
\exp(-i \theta Y^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_y_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, FLOAT_T], [block_type]),
)
# pauli_exp_all_z
@functools.cached_property
def pauli_exp_all_z_def(self) -> OpDef:
r"""Apply the logical all-Z Pauli exponential.
.. math::
\exp(-i \theta Z^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_z``.
"""
return self().get_op("pauli_exp_all_z")
[docs]
def pauli_exp_all_z(self, k: int) -> ExtOp:
r"""Apply the logical all-Z Pauli exponential.
.. math::
\exp(-i \theta Z^{\otimes k} / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, FLOAT_T], [block_type]),
)
# pauli_exp_all_x_except_at
@functools.cached_property
def pauli_exp_all_x_except_at_def(self) -> OpDef:
r"""Apply the Pauli exponential with I at ``i`` and X elsewhere.
.. math::
\exp(-i \theta (
X^{\otimes i} \otimes I \otimes X^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_x_except_at``.
"""
return self().get_op("pauli_exp_all_x_except_at")
[docs]
def pauli_exp_all_x_except_at(self, k: int) -> ExtOp:
r"""Apply the Pauli exponential with I at ``i`` and X elsewhere.
.. math::
\exp(-i \theta (
X^{\otimes i} \otimes I \otimes X^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_x_except_at_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# pauli_exp_all_z_except_at
@functools.cached_property
def pauli_exp_all_z_except_at_def(self) -> OpDef:
r"""Apply the Pauli exponential with I at ``i`` and Z elsewhere.
.. math::
\exp(-i \theta (
Z^{\otimes i} \otimes I \otimes Z^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_z_except_at``.
"""
return self().get_op("pauli_exp_all_z_except_at")
[docs]
def pauli_exp_all_z_except_at(self, k: int) -> ExtOp:
r"""Apply the Pauli exponential with I at ``i`` and Z elsewhere.
.. math::
\exp(-i \theta (
Z^{\otimes i} \otimes I \otimes Z^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_z_except_at_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# pauli_exp_all_x_except_z_at
@functools.cached_property
def pauli_exp_all_x_except_z_at_def(self) -> OpDef:
r"""Apply the Pauli exponential with Z at ``i`` and X elsewhere.
.. math::
\exp(-i \theta (
X^{\otimes i} \otimes Z \otimes X^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_x_except_z_at``.
"""
return self().get_op("pauli_exp_all_x_except_z_at")
[docs]
def pauli_exp_all_x_except_z_at(self, k: int) -> ExtOp:
r"""Apply the Pauli exponential with Z at ``i`` and X elsewhere.
.. math::
\exp(-i \theta (
X^{\otimes i} \otimes Z \otimes X^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_x_except_z_at_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# pauli_exp_all_z_except_x_at
@functools.cached_property
def pauli_exp_all_z_except_x_at_def(self) -> OpDef:
r"""Apply the Pauli exponential with X at ``i`` and Z elsewhere.
.. math::
\exp(-i \theta (
Z^{\otimes i} \otimes X \otimes Z^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
This is the generic operation definition. For the instantiated
operation, see ``pauli_exp_all_z_except_x_at``.
"""
return self().get_op("pauli_exp_all_z_except_x_at")
[docs]
def pauli_exp_all_z_except_x_at(self, k: int) -> ExtOp:
r"""Apply the Pauli exponential with X at ``i`` and Z elsewhere.
.. math::
\exp(-i \theta (
Z^{\otimes i} \otimes X \otimes Z^{\otimes(k-i-1)}
) / 2)
The operation's angle :math:`\theta` is in radians and :math:`k`
is the number of logical qubits in the block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.pauli_exp_all_z_except_x_at_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, FLOAT_T], [block_type]
),
)
# all_h
@functools.cached_property
def all_h_def(self) -> OpDef:
"""Apply an H gate to all qubits.
This is the generic operation definition. For the instantiated operation, see
`all_h`."""
return self().get_op("all_h")
[docs]
def all_h(self, k: int) -> ExtOp:
"""Apply an H gate to all qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.all_h_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type], [block_type]),
)
# xx_phase
@functools.cached_property
def xx_phase_def(self) -> OpDef:
"""Apply an XXPhase gate to two qubits within a block.
This is the generic operation definition. For the instantiated operation, see
`xx_phase`."""
return self().get_op("xx_phase")
[docs]
def xx_phase(self, k: int) -> ExtOp:
"""Apply an XXPhase gate to two qubits within a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.xx_phase_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, _IDX_T, FLOAT_T], [block_type]
),
)
# yy_phase
@functools.cached_property
def yy_phase_def(self) -> OpDef:
"""Apply a YYPhase gate to two qubits within a block.
This is the generic operation definition. For the instantiated operation, see
`yy_phase`."""
return self().get_op("yy_phase")
[docs]
def yy_phase(self, k: int) -> ExtOp:
"""Apply a YYPhase gate to two qubits within a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.yy_phase_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, _IDX_T, FLOAT_T], [block_type]
),
)
# zz_phase
@functools.cached_property
def zz_phase_def(self) -> OpDef:
"""Apply a ZZPhase gate to two qubits within a block.
This is the generic operation definition. For the instantiated operation, see
`zz_phase`."""
return self().get_op("zz_phase")
[docs]
def zz_phase(self, k: int) -> ExtOp:
"""Apply a ZZPhase gate to two qubits within a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.zz_phase_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T, _IDX_T, FLOAT_T], [block_type]
),
)
# cx
@functools.cached_property
def cx_def(self) -> OpDef:
"""Apply a CX gate to two qubits within a block.
This is the generic operation definition. For the instantiated operation, see
`cx`."""
return self().get_op("cx")
[docs]
def cx(self, k: int) -> ExtOp:
"""Apply a CX gate to two qubits within a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.cx_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T, _IDX_T], [block_type]),
)
# swap
@functools.cached_property
def swap_def(self) -> OpDef:
"""Apply a SWAP gate to two qubits within a block.
This is the generic operation definition. For the instantiated operation, see
`swap`."""
return self().get_op("swap")
[docs]
def swap(self, k: int) -> ExtOp:
"""Apply a SWAP gate to two qubits within a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.swap_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type, _IDX_T, _IDX_T], [block_type]),
)
# xx_phase_between_blocks
@functools.cached_property
def xx_phase_between_blocks_def(self) -> OpDef:
"""Apply an XXPhase gate to two qubits on different blocks of the same size with
dynamic indices.
This is the generic operation definition. For the instantiated operation, see
`xx_phase_between_blocks`."""
return self().get_op("xx_phase_between_blocks")
[docs]
def xx_phase_between_blocks(self, k: int) -> ExtOp:
"""Apply an XXPhase gate to two qubits on different blocks of the same size with
dynamic indices.
Args:
k: The number of logical qubits encoded in the blocks.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.xx_phase_between_blocks_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, block_type, _IDX_T, _IDX_T, FLOAT_T],
[block_type, block_type],
),
)
# yy_phase_between_blocks
@functools.cached_property
def yy_phase_between_blocks_def(self) -> OpDef:
"""Apply a YYPhase gate to two qubits on different blocks of the same size with
dynamic indices.
This is the generic operation definition. For the instantiated operation, see
`yy_phase_between_blocks`."""
return self().get_op("yy_phase_between_blocks")
[docs]
def yy_phase_between_blocks(self, k: int) -> ExtOp:
"""Apply a YYPhase gate to two qubits on different blocks of the same size with
dynamic indices.
Args:
k: The number of logical qubits encoded in the blocks.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.yy_phase_between_blocks_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, block_type, _IDX_T, _IDX_T, FLOAT_T],
[block_type, block_type],
),
)
# zz_phase_between_blocks
@functools.cached_property
def zz_phase_between_blocks_def(self) -> OpDef:
"""Apply a ZZPhase gate to two qubits on different blocks of the same size with
dynamic indices.
This is the generic operation definition. For the instantiated operation, see
`zz_phase_between_blocks`."""
return self().get_op("zz_phase_between_blocks")
[docs]
def zz_phase_between_blocks(self, k: int) -> ExtOp:
"""Apply a ZZPhase gate to two qubits on different blocks of the same size with
dynamic indices.
Args:
k: The number of logical qubits encoded in the blocks.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.zz_phase_between_blocks_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, block_type, _IDX_T, _IDX_T, FLOAT_T],
[block_type, block_type],
),
)
# cx_between_blocks
@functools.cached_property
def cx_between_blocks_def(self) -> OpDef:
"""Apply a CX gate to two qubits on different blocks of the same size with
dynamic indices.
This is the generic operation definition. For the instantiated operation, see
`cx_between_blocks`."""
return self().get_op("cx_between_blocks")
[docs]
def cx_between_blocks(self, k: int) -> ExtOp:
"""Apply a CX gate to two qubits on different blocks of the same size with
dynamic indices.
Args:
k: The number of logical qubits encoded in the blocks.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.cx_between_blocks_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, block_type, _IDX_T, _IDX_T], [block_type, block_type]
),
)
# cx_transversal
@functools.cached_property
def cx_transversal_def(self) -> OpDef:
"""Apply a CX gate transversally over two blocks of the same size.
This is the generic operation definition. For the instantiated operation, see
`cx_transversal`."""
return self().get_op("cx_transversal")
[docs]
def cx_transversal(self, k: int) -> ExtOp:
"""Apply a CX gate transversally over two blocks of the same size.
Args:
k: The number of logical qubits encoded in the blocks.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.cx_transversal_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, block_type], [block_type, block_type]
),
)
# alloc_zero
@functools.cached_property
def alloc_zero_def(self) -> OpDef:
"""Allocate a block in the all-zero state.
This is the generic operation definition. For the instantiated operation, see
`alloc_zero`."""
return self().get_op("alloc_zero")
[docs]
def alloc_zero(self, k: int) -> ExtOp:
"""Allocate a block in the all-zero state.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.alloc_zero_def.instantiate(
args=[BoundedNatArg(k)], concrete_signature=FunctionType([], [block_type])
)
# try_alloc_zero
@functools.cached_property
def try_alloc_zero_def(self) -> OpDef:
"""Allocate a `PreBlock` in the all-zero state.
This is the generic operation definition. For the instantiated operation, see
`alloc_zero`."""
return self().get_op("try_alloc_zero")
[docs]
def try_alloc_zero(self, k: int) -> ExtOp:
"""Allocate a `PreBlock` in the all-zero state.
Args:
k: The number of logical qubits encoded in the block.
"""
preblock_type = _ICEBERG_TYPES.iceberg_pre_block(k)
return self.try_alloc_zero_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([], [preblock_type]),
)
# check_pre_block
@functools.cached_property
def check_pre_block_def(self) -> OpDef:
"""Check if a `PreBlock` is in a valid logical state.
This is the generic operation definition. For the instantiated operation, see
`check`."""
return self().get_op("check_pre_block")
[docs]
def check_pre_block(self, k: int) -> ExtOp:
"""Check if a `PreBlock` is in a valid logical state.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
preblock_type = _ICEBERG_TYPES.iceberg_pre_block(k)
return self.check_pre_block_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([preblock_type], [Option(block_type)]),
)
# free
@functools.cached_property
def free_def(self) -> OpDef:
"""Free a block.
This is the generic operation definition. For the instantiated operation, see
`free`."""
return self().get_op("free")
[docs]
def free(self, k: int) -> ExtOp:
"""Free a block.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.free_def.instantiate(
args=[BoundedNatArg(k)], concrete_signature=FunctionType([block_type], [])
)
# measure_syndrome
@functools.cached_property
def measure_syndrome_def(self) -> OpDef:
"""Perform a syndrome measurement, producing (X,Z) error indicators.
This is the generic operation definition. For the instantiated operation, see
`measure_syndrome`."""
return self().get_op("measure_syndrome")
[docs]
def measure_syndrome(self, k: int) -> ExtOp:
"""Perform a syndrome measurement, producing (X,Z) error indicators.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.measure_syndrome_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type], [block_type, _MEAS_T, _MEAS_T]
),
)
# measure_all
@functools.cached_property
def measure_all_def(self) -> OpDef:
"""Destructively measure all qubits in the Z basis.
This is the generic operation definition. For the instantiated operation, see
`measure_all`."""
return self().get_op("measure_all")
[docs]
def measure_all(self, k: int) -> ExtOp:
"""Destructively measure all qubits in the Z basis.
Args:
k: The number of logical qubits encoded in the block.
"""
from guppyft.extensions import std_types
block_type = _ICEBERG_TYPES.iceberg_block(k)
lmeas_type = std_types.logical_measurement(k)
return self.measure_all_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType([block_type], [lmeas_type]),
)
# try_measure_one_x
@functools.cached_property
def try_measure_one_x_def(self) -> OpDef:
"""Non-destructively measure one qubit in the X basis.
This operation is fallible and produces a future optional bool. A "none"
value indicates a probable single-qubit error; QED may then be used to
detect whether this was just a measurement error or whether it affected
the data qubits.
This is the generic operation definition. For the instantiated operation, see
`try_measure_one_x`."""
return self().get_op("try_measure_one_x")
[docs]
def try_measure_one_x(self, k: int) -> ExtOp:
"""Non-destructively measure one qubit in the X basis.
This operation is fallible and produces a future optional bool. A "none"
value indicates a probable single-qubit error; QED may then be used to
detect whether this was just a measurement error or whether it affected
the data qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.try_measure_one_x_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T], [Option(_MEAS_T), block_type]
),
)
# try_measure_one_z
@functools.cached_property
def try_measure_one_z_def(self) -> OpDef:
"""Non-destructively measure one qubit in the Z basis.
This operation is fallible and produces a future optional bool. A "none"
value indicates a probable single-qubit error; QED may then be used to
detect whether this was just a measurement error or whether it affected
the data qubits.
This is the generic operation definition. For the instantiated operation, see
`try_measure_one_z`."""
return self().get_op("try_measure_one_z")
[docs]
def try_measure_one_z(self, k: int) -> ExtOp:
"""Non-destructively measure one qubit in the Z basis.
This operation is fallible and produces a future optional bool. A "none"
value indicates a probable single-qubit error; QED may then be used to
detect whether this was just a measurement error or whether it affected
the data qubits.
Args:
k: The number of logical qubits encoded in the block.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
return self.try_measure_one_z_def.instantiate(
args=[BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type, _IDX_T], [Option(_MEAS_T), block_type]
),
)
# alloc_dynq
@functools.cached_property
def alloc_dynq_def(self) -> OpDef:
"""Allocate a dynamic logical qubit in the zero state.
This is the generic operation definition. For the instantiated operation, see
`alloc_dynq`."""
return self().get_op("alloc_dynq")
@functools.cached_property
def alloc_dynq(self) -> ExtOp:
"""Allocate a dynamic logical qubit in the zero state."""
return self.alloc_dynq_def.instantiate([])
# try_alloc_dynq
@functools.cached_property
def try_alloc_dynq_def(self) -> OpDef:
"""Try to allocate a dynamic logical qubit in the zero state.
This is the generic operation definition. For the instantiated operation, see
`try_alloc_dynq`."""
return self().get_op("try_alloc_dynq")
@functools.cached_property
def try_alloc_dynq(self) -> ExtOp:
"""Try to allocate a dynamic logical qubit in the zero state."""
return self.try_alloc_dynq_def.instantiate([])
# free_dynq
@functools.cached_property
def free_dynq_def(self) -> OpDef:
"""Discard a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`free_dynq`."""
return self().get_op("free_dynq")
@functools.cached_property
def free_dynq(self) -> ExtOp:
"""Discard a dynamic logical qubit."""
return self.free_dynq_def.instantiate([])
# x_dynq
@functools.cached_property
def x_dynq_def(self) -> OpDef:
"""X gate on a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`x_dynq`."""
return self().get_op("x_dynq")
@functools.cached_property
def x_dynq(self) -> ExtOp:
"""X gate on a dynamic logical qubit."""
return self.x_dynq_def.instantiate([])
# y_dynq
@functools.cached_property
def y_dynq_def(self) -> OpDef:
"""Y gate on a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`y_dynq`."""
return self().get_op("y_dynq")
@functools.cached_property
def y_dynq(self) -> ExtOp:
"""Y gate on a dynamic logical qubit."""
return self.y_dynq_def.instantiate([])
# z_dynq
@functools.cached_property
def z_dynq_def(self) -> OpDef:
"""Z gate on a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`z_dynq`."""
return self().get_op("z_dynq")
@functools.cached_property
def z_dynq(self) -> ExtOp:
"""Z gate on a dynamic logical qubit."""
return self.z_dynq_def.instantiate([])
# rx_dynq
@functools.cached_property
def rx_dynq_def(self) -> OpDef:
"""Rx gate on a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`rx_dynq`."""
return self().get_op("rx_dynq")
@functools.cached_property
def rx_dynq(self) -> ExtOp:
"""Rx gate on a dynamic logical qubit."""
return self.rx_dynq_def.instantiate([])
# rz_dynq
@functools.cached_property
def rz_dynq_def(self) -> OpDef:
"""Rz gate on a dynamic logical qubit.
This is the generic operation definition. For the instantiated operation, see
`rz_dynq`."""
return self().get_op("rz_dynq")
@functools.cached_property
def rz_dynq(self) -> ExtOp:
"""Rz gate on a dynamic logical qubit."""
return self.rz_dynq_def.instantiate([])
# xx_phase_dynq
@functools.cached_property
def xx_phase_dynq_def(self) -> OpDef:
"""XXPhase gate on two dynamic logical qubits.
This is the generic operation definition. For the instantiated operation, see
`xx_phase_dynq`."""
return self().get_op("xx_phase_dynq")
@functools.cached_property
def xx_phase_dynq(self) -> ExtOp:
"""XXPhase gate on two dynamic logical qubits."""
return self.xx_phase_dynq_def.instantiate([])
# yy_phase_dynq
@functools.cached_property
def yy_phase_dynq_def(self) -> OpDef:
"""YYPhase gate on two dynamic logical qubits.
This is the generic operation definition. For the instantiated operation, see
`yy_phase_dynq`."""
return self().get_op("yy_phase_dynq")
@functools.cached_property
def yy_phase_dynq(self) -> ExtOp:
"""YYPhase gate on two dynamic logical qubits."""
return self.yy_phase_dynq_def.instantiate([])
# zz_phase_dynq
@functools.cached_property
def zz_phase_dynq_def(self) -> OpDef:
"""ZZPhase gate on two dynamic logical qubits.
This is the generic operation definition. For the instantiated operation, see
`zz_phase_dynq`."""
return self().get_op("zz_phase_dynq")
@functools.cached_property
def zz_phase_dynq(self) -> ExtOp:
"""ZZPhase gate on two dynamic logical qubits."""
return self.zz_phase_dynq_def.instantiate([])
# cx_dynq
@functools.cached_property
def cx_dynq_def(self) -> OpDef:
"""CX gate on two dynamic logical qubits.
This is the generic operation definition. For the instantiated operation, see
`cx_dynq`."""
return self().get_op("cx_dynq")
@functools.cached_property
def cx_dynq(self) -> ExtOp:
"""CX gate on two dynamic logical qubits."""
return self.cx_dynq_def.instantiate([])
# try_measure_x_dynq
@functools.cached_property
def try_measure_x_dynq_def(self) -> OpDef:
"""Fallible non-destructive measurement of a dynamic logical qubit in the X
basis.
This is the generic operation definition. For the instantiated operation, see
`try_measure_x_dynq`."""
return self().get_op("try_measure_x_dynq")
@functools.cached_property
def try_measure_x_dynq(self) -> ExtOp:
"""Fallible non-destructive measurement of a dynamic logical qubit in the X
basis."""
return self.try_measure_x_dynq_def.instantiate([])
# try_measure_z_dynq
@functools.cached_property
def try_measure_z_dynq_def(self) -> OpDef:
"""Fallible non-destructive measurement of a dynamic logical qubit in the Z
basis.
This is the generic operation definition. For the instantiated operation, see
`try_measure_z_dynq`."""
return self().get_op("try_measure_z_dynq")
@functools.cached_property
def try_measure_z_dynq(self) -> ExtOp:
"""Fallible non-destructive measurement of a dynamic logical qubit in the Z
basis."""
return self.try_measure_z_dynq_def.instantiate([])
# borrow
@functools.cached_property
def borrow_def(self) -> OpDef:
"""Extraction of dynamic logical qubits from a block.
This is the generic operation definition. For the instantiated operation, see
`borrow`."""
return self().get_op("borrow")
[docs]
def borrow(self, k: int, m: int) -> ExtOp:
"""Extraction of dynamic logical qubits from a block.
Args:
k: The number of logical qubits encoded in the block.
m: The number of logical qubits to borrow.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
bblock_type = _ICEBERG_TYPES.iceberg_borrowed_block(k)
return self.borrow_def.instantiate(
args=[BoundedNatArg(m), BoundedNatArg(k)],
concrete_signature=FunctionType(
[block_type] + [_IDX_T] * m, # type: ignore[arg-type]
[bblock_type] + [_DYNQ_T] * m, # type: ignore[arg-type]
),
)
# borrow_more
@functools.cached_property
def borrow_more_def(self) -> OpDef:
"""Extraction of dynamic logical qubits from an already-borrowed block.
This is the generic operation definition. For the instantiated operation, see
`borrow_more`."""
return self().get_op("borrow_more")
[docs]
def borrow_more(self, k: int, m: int) -> ExtOp:
"""Extraction of dynamic logical qubits from an already-borrowed block.
Args:
k: The number of logical qubits encoded in the block.
m: The number of logical qubits to borrow.
"""
bblock_type = _ICEBERG_TYPES.iceberg_borrowed_block(k)
return self.borrow_more_def.instantiate(
args=[BoundedNatArg(m), BoundedNatArg(k)],
concrete_signature=FunctionType(
[bblock_type] + [_IDX_T] * m, # type: ignore[arg-type]
[bblock_type] + [_DYNQ_T] * m, # type: ignore[arg-type]
),
)
# restore_some
@functools.cached_property
def restore_some_def(self) -> OpDef:
"""Restoration of some dynamic logical qubits to their originating block.
This is the generic operation definition. For the instantiated operation, see
`restore_some`."""
return self().get_op("restore_some")
[docs]
def restore_some(self, k: int, m: int) -> ExtOp:
"""Restoration of some dynamic logical qubits to their originating block.
Args:
k: The number of logical qubits encoded in the block.
m: The number of logical qubits to restore.
"""
bblock_type = _ICEBERG_TYPES.iceberg_borrowed_block(k)
return self.restore_some_def.instantiate(
args=[BoundedNatArg(m), BoundedNatArg(k)],
concrete_signature=FunctionType(
[bblock_type] + [_DYNQ_T] * m, # type: ignore[arg-type]
[bblock_type],
),
)
# restore
@functools.cached_property
def restore_def(self) -> OpDef:
"""Restoration of all dynamic logical qubits to their originating block.
This is the generic operation definition. For the instantiated operation, see
`restore`."""
return self().get_op("restore")
[docs]
def restore(self, k: int, m: int) -> ExtOp:
"""Restoration of all dynamic logical qubits to their originating block.
Args:
k: The number of logical qubits encoded in the block.
m: The number of logical qubits to restore.
"""
block_type = _ICEBERG_TYPES.iceberg_block(k)
bblock_type = _ICEBERG_TYPES.iceberg_borrowed_block(k)
return self.restore_def.instantiate(
args=[BoundedNatArg(m), BoundedNatArg(k)],
concrete_signature=FunctionType(
[bblock_type] + [_DYNQ_T] * m, # type: ignore[arg-type]
[block_type],
),
)