Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions guppylang/src/guppylang/std/qsystem/helios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
QSYSTEM_HELIOS_EXTENSION,
)
from guppylang_internals.std._internal.util import quantum_op
from guppylang_internals.tys.ty import UnitaryFlags

from guppylang import guppy
from guppylang.std.angles import angle, pi
Expand Down Expand Up @@ -57,7 +58,7 @@
]


@guppy
@guppy(unitary=True)
@no_type_check
def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
r"""Primitive phased_x gate command.
Expand All @@ -78,7 +79,7 @@ def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
_phased_x(q, f1, f2)


@guppy
@guppy(unitary=True)
@no_type_check
def zz_max(q1: qubit, q2: qubit) -> None:
r"""zz_max gate command. A maximally entangling zz_phase gate.
Expand All @@ -103,7 +104,7 @@ def zz_max(q1: qubit, q2: qubit) -> None:
zz_phase(q1, q2, pi / 2)


@guppy
@guppy(unitary=True)
@no_type_check
def zz_phase(q1: qubit, q2: qubit, angle: angle) -> None:
r"""Primitive zz_phase gate command.
Expand All @@ -126,7 +127,7 @@ def zz_phase(q1: qubit, q2: qubit, angle: angle) -> None:
_zz_phase(q1, q2, f)


@guppy
@guppy(unitary=True)
@no_type_check
def rz(q: qubit, angle: angle) -> None:
r"""Primitive rz gate command.
Expand Down Expand Up @@ -285,7 +286,10 @@ def lazy_measure_and_reset_array(
# ------------------------------------------------------


@hugr_op(quantum_op("PhasedX", ext=QSYSTEM_HELIOS_EXTENSION))
@hugr_op(
quantum_op("PhasedX", ext=QSYSTEM_HELIOS_EXTENSION),
unitary_flags=UnitaryFlags.Unitary,
)
@no_type_check
def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""PhasedX operation from the qsystem extension.
Expand All @@ -295,7 +299,10 @@ def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""


@hugr_op(quantum_op("ZZPhase", ext=QSYSTEM_HELIOS_EXTENSION))
@hugr_op(
quantum_op("ZZPhase", ext=QSYSTEM_HELIOS_EXTENSION),
unitary_flags=UnitaryFlags.Unitary,
)
@no_type_check
def _zz_phase(q1: qubit, q2: qubit, angle: float) -> None:
"""ZZPhase operation from the qsystem extension.
Expand All @@ -305,7 +312,9 @@ def _zz_phase(q1: qubit, q2: qubit, angle: float) -> None:
"""


@hugr_op(quantum_op("Rz", ext=QSYSTEM_HELIOS_EXTENSION))
@hugr_op(
quantum_op("Rz", ext=QSYSTEM_HELIOS_EXTENSION), unitary_flags=UnitaryFlags.Unitary
)
@no_type_check
def _rz(q: qubit, angle: float) -> None:
"""Rz operation from the qsystem extension.
Expand Down
26 changes: 17 additions & 9 deletions guppylang/src/guppylang/std/qsystem/sol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
QSYSTEM_SOL_EXTENSION,
)
from guppylang_internals.std._internal.util import quantum_op
from guppylang_internals.tys.ty import UnitaryFlags

from guppylang import guppy
from guppylang.std.angles import angle, pi
Expand Down Expand Up @@ -59,7 +60,7 @@
]


@guppy
@guppy(unitary=True)
@no_type_check
def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
r"""Primitive phased_x gate command.
Expand All @@ -80,7 +81,7 @@ def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
_phased_x(q, f1, f2)


@guppy
@guppy(unitary=True)
@no_type_check
def phased_xx(q1: qubit, q2: qubit, angle1: angle, angle2: angle) -> None:
r"""Primitive phased_xx gate command. The native 2-qubit entangling gate on Sol.
Expand Down Expand Up @@ -112,7 +113,7 @@ def phased_xx(q1: qubit, q2: qubit, angle1: angle, angle2: angle) -> None:
_phased_xx(q1, q2, f1, f2)


@guppy
@guppy(unitary=True)
@no_type_check
def phased_xx_max(q1: qubit, q2: qubit, phase: angle) -> None:
r"""phased_xx_max gate command. Maximally entangling PhasedXX gate at a given phase.
Expand All @@ -133,7 +134,7 @@ def phased_xx_max(q1: qubit, q2: qubit, phase: angle) -> None:
phased_xx(q1, q2, pi / 2, phase)


@guppy
@guppy(unitary=True)
@no_type_check
def xx_max(q1: qubit, q2: qubit) -> None:
r"""xx_max gate command. Maximally entangling XX gate.
Expand All @@ -144,7 +145,7 @@ def xx_max(q1: qubit, q2: qubit) -> None:
phased_xx_max(q1, q2, angle(0.0))


@guppy
@guppy(unitary=True)
@no_type_check
def yy_max(q1: qubit, q2: qubit) -> None:
r"""yy_max gate command. Maximally entangling YY gate.
Expand All @@ -157,7 +158,7 @@ def yy_max(q1: qubit, q2: qubit) -> None:
phased_xx_max(q1, q2, pi / 2)


@guppy
@guppy(unitary=True)
@no_type_check
def rz(q: qubit, angle: angle) -> None:
r"""Primitive rz gate command.
Expand Down Expand Up @@ -315,7 +316,9 @@ def lazy_measure_and_reset_array(
# ------------------------------------------------------


@hugr_op(quantum_op("PhasedX", ext=QSYSTEM_SOL_EXTENSION))
@hugr_op(
quantum_op("PhasedX", ext=QSYSTEM_SOL_EXTENSION), unitary_flags=UnitaryFlags.Unitary
)
@no_type_check
def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""PhasedX operation from the qsystem sol extension.
Expand All @@ -325,7 +328,10 @@ def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""


@hugr_op(quantum_op("PhasedXX", ext=QSYSTEM_SOL_EXTENSION))
@hugr_op(
quantum_op("PhasedXX", ext=QSYSTEM_SOL_EXTENSION),
unitary_flags=UnitaryFlags.Unitary,
)
@no_type_check
def _phased_xx(q1: qubit, q2: qubit, angle1: float, angle2: float) -> None:
"""PhasedXX operation from the qsystem sol extension.
Expand All @@ -335,7 +341,9 @@ def _phased_xx(q1: qubit, q2: qubit, angle1: float, angle2: float) -> None:
"""


@hugr_op(quantum_op("Rz", ext=QSYSTEM_SOL_EXTENSION))
@hugr_op(
quantum_op("Rz", ext=QSYSTEM_SOL_EXTENSION), unitary_flags=UnitaryFlags.Unitary
)
@no_type_check
def _rz(q: qubit, angle: float) -> None:
"""Rz operation from the qsystem sol extension.
Expand Down
84 changes: 83 additions & 1 deletion tests/integration/test_qsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import guppylang.std.qsystem.sol.functional as sol_fn_mod
from guppylang.decorator import guppy
from guppylang.std.angles import angle
from guppylang.std.builtins import array, owned
from guppylang.std.builtins import array, control, dagger, owned
from typing import NamedTuple
from types import ModuleType

from guppylang_internals.error import GuppyError

from guppylang.std.qsystem.random import RNG, make_discrete_distribution
from guppylang.std.qsystem.utils import get_current_shot
from guppylang.std.quantum import Measurement, measure_array, qubit, x
Expand Down Expand Up @@ -78,6 +80,86 @@ def test(q1: qubit @ owned, q2: qubit @ owned, a1: angle) -> Measurement:
validate(test.compile_function())


def test_qsystem_helios_unitary(): # type: ignore[no-untyped-def]
"""The unitary Helios gates can be used under `dagger` and `control` modifiers.

Only type checking is exercised here: lowering a controlled/daggered qsystem
hardware primitive is not yet supported by the tket normalization pass.
"""
from guppylang.std.qsystem.helios import phased_x, rz, zz_max, zz_phase

@guppy
def use_dagger(q1: qubit, q2: qubit, a: angle) -> None:
with dagger:
phased_x(q1, a, a)
rz(q1, a)
zz_phase(q1, q2, a)
zz_max(q1, q2)

@guppy
def use_control(ctrl: qubit, q1: qubit, q2: qubit, a: angle) -> None:
with control(ctrl):
phased_x(q1, a, a)
rz(q1, a)
zz_phase(q1, q2, a)
zz_max(q1, q2)

use_dagger.check()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change this when the tket2 passes are ready

use_control.check()


def test_qsystem_sol_unitary(): # type: ignore[no-untyped-def]
"""The unitary Sol gates can be used under `dagger` and `control` modifiers.

Only type checking is exercised here: lowering a controlled/daggered qsystem
hardware primitive is not yet supported by the tket normalization pass.
"""
from guppylang.std.qsystem.sol import (
phased_x,
phased_xx,
phased_xx_max,
rz,
xx_max,
yy_max,
)

@guppy
def use_dagger(q1: qubit, q2: qubit, a: angle) -> None:
with dagger:
phased_x(q1, a, a)
rz(q1, a)
phased_xx(q1, q2, a, a)
phased_xx_max(q1, q2, a)
xx_max(q1, q2)
yy_max(q1, q2)

@guppy
def use_control(ctrl: qubit, q1: qubit, q2: qubit, a: angle) -> None:
with control(ctrl):
phased_x(q1, a, a)
rz(q1, a)
phased_xx(q1, q2, a, a)
phased_xx_max(q1, q2, a)
xx_max(q1, q2)
yy_max(q1, q2)

use_dagger.check()
use_control.check()


def test_qsystem_non_unitary_rejected(qsys_mod: QsysMod): # type: ignore[no-untyped-def]
"""Non-unitary operations (e.g. reset) cannot be used in a unitary context."""
mod = qsys_mod.mod

@guppy
def use_reset_dagger(q: qubit) -> None:
with dagger:
mod.reset(q)

with pytest.raises(GuppyError):
use_reset_dagger.check()


def test_qsystem_random(validate): # type: ignore[no-untyped-def]
"""Compile various operations from the qsystem random extension."""
from guppylang.std.qsystem.helios import collect_measurements
Expand Down
Loading