Skip to content

Commit

Permalink
feat!: qsystem std functions with updated primitives (#679)
Browse files Browse the repository at this point in the history
Closes #625 Closes #645
- hseries renamed to qsystem



BREAKING CHANGE: hseries primitive functions moved to std.qsystem
BREAKING CHANGE: measure_return renamed to `project_z`
  • Loading branch information
ss2165 authored Dec 2, 2024
1 parent 1031cb4 commit b0f041f
Show file tree
Hide file tree
Showing 12 changed files with 283 additions and 130 deletions.
23 changes: 17 additions & 6 deletions guppylang/std/_internal/compiler/quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from __future__ import annotations

from hugr import Wire, ops
from hugr import ext as he
from hugr import tys as ht
from hugr.std.float import FLOAT_T
from tket2_exts import futures, hseries, quantum, result, rotation
from tket2_exts import futures, qsystem, quantum, result, rotation

from guppylang.definition.custom import CustomInoutCallCompiler
from guppylang.definition.value import CallReturnWires
Expand All @@ -17,7 +18,7 @@
# ----------------------------------------------

FUTURES_EXTENSION = futures()
HSERIES_EXTENSION = hseries()
QSYSTEM_EXTENSION = qsystem()
QUANTUM_EXTENSION = quantum()
RESULT_EXTENSION = result()
ROTATION_EXTENSION = rotation()
Expand All @@ -27,7 +28,7 @@

TKET2_EXTENSIONS = [
FUTURES_EXTENSION,
HSERIES_EXTENSION,
QSYSTEM_EXTENSION,
QUANTUM_EXTENSION,
RESULT_EXTENSION,
ROTATION_EXTENSION,
Expand All @@ -46,15 +47,25 @@ def from_halfturns_unchecked() -> ops.ExtOp:
# ------------------------------------------------------


class MeasureReturnCompiler(CustomInoutCallCompiler):
"""Compiler for the `measure_return` function."""
class InoutMeasureCompiler(CustomInoutCallCompiler):
"""Compiler for the measure functions with an inout qubit
such as the `project_z` function."""

opname: str
ext: he.Extension

def __init__(self, opname: str | None = None, ext: he.Extension | None = None):
self.opname = opname or "Measure"
self.ext = ext or QUANTUM_EXTENSION

def compile_with_inouts(self, args: list[Wire]) -> CallReturnWires:
from guppylang.std._internal.util import quantum_op

[q] = args
[q, bit] = self.builder.add_op(
quantum_op("Measure")(ht.FunctionType([ht.Qubit], [ht.Qubit, ht.Bool]), []),
quantum_op(self.opname, ext=self.ext)(
ht.FunctionType([ht.Qubit], [ht.Qubit, ht.Bool]), []
),
q,
)
return CallReturnWires(regular_returns=[bit], inout_returns=[q])
Expand Down
108 changes: 108 additions & 0 deletions guppylang/std/qsystem/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
from typing import no_type_check

from guppylang.decorator import guppy
from guppylang.module import GuppyModule
from guppylang.std import angles
from guppylang.std._internal.compiler.quantum import (
QSYSTEM_EXTENSION,
InoutMeasureCompiler,
)
from guppylang.std._internal.util import quantum_op
from guppylang.std.angles import angle
from guppylang.std.builtins import owned
from guppylang.std.quantum import qubit

qsystem = GuppyModule("qsystem")

qsystem.load(qubit)
qsystem.load_all(angles)


@guppy(qsystem)
@no_type_check
def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
f1 = float(angle1)
f2 = float(angle2)
_phased_x(q, f1, f2)


@guppy.hugr_op(quantum_op("ZZMax", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def zz_max(q1: qubit, q2: qubit) -> None: ...


@guppy(qsystem)
@no_type_check
def zz_phase(q1: qubit, q2: qubit, angle: angle) -> None:
f = float(angle)
_zz_phase(q1, q2, f)


@guppy(qsystem)
@no_type_check
def rz(q: qubit, angle: angle) -> None:
f1 = float(angle)
_rz(q, f1)


@guppy.hugr_op(quantum_op("Measure", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def measure(q: qubit @ owned) -> bool: ...


@guppy.custom(InoutMeasureCompiler("MeasureReset", QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def measure_and_reset(q: qubit) -> bool:
"""MeasureReset operation from the qsystem extension."""


@guppy.hugr_op(quantum_op("Reset", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def reset(q: qubit) -> None: ...


# TODO
# @guppy.hugr_op(quantum_op("TryQAlloc", ext=QSYSTEM_EXTENSION), module=qsystem)
# @no_type_check
# def _try_qalloc() -> Option[qubit]:
# ..


@guppy.hugr_op(quantum_op("QFree", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def qfree(q: qubit @ owned) -> None: ...


# ------------------------------------------------------
# --------- Internal definitions -----------------------
# ------------------------------------------------------


@guppy.hugr_op(quantum_op("PhasedX", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""PhasedX operation from the qsystem extension.
See `guppylang.std.qsystem.phased_x` for a public definition that
accepts angle parameters.
"""


@guppy.hugr_op(quantum_op("ZZPhase", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def _zz_phase(q1: qubit, q2: qubit, angle: float) -> None:
"""ZZPhase operation from the qsystem extension.
See `guppylang.std.qsystem.phased_x` for a public definition that
accepts angle parameters.
"""


@guppy.hugr_op(quantum_op("Rz", ext=QSYSTEM_EXTENSION), module=qsystem)
@no_type_check
def _rz(q: qubit, angle: float) -> None:
"""Rz operation from the qsystem extension.
See `guppylang.std.qsystem.rz` for a public definition that
accepts angle parameters.
"""
68 changes: 68 additions & 0 deletions guppylang/std/qsystem/functional.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from typing import no_type_check

from guppylang.decorator import guppy
from guppylang.module import GuppyModule
from guppylang.std import angles, qsystem
from guppylang.std.angles import angle
from guppylang.std.builtins import owned
from guppylang.std.quantum import qubit

qsystem_functional = GuppyModule("qsystem_functional")

qsystem_functional.load(qubit, qsystem)
qsystem_functional.load_all(angles)


@guppy(qsystem_functional)
@no_type_check
def phased_x(q: qubit @ owned, angle1: angle, angle2: angle) -> qubit:
qsystem.phased_x(q, angle1, angle2)
return q


@guppy(qsystem_functional)
@no_type_check
def zz_phase(q1: qubit @ owned, q2: qubit @ owned, angle: angle) -> tuple[qubit, qubit]:
qsystem.zz_phase(q1, q2, angle)
return q1, q2


@guppy(qsystem_functional)
@no_type_check
def measure_and_reset(q: qubit @ owned) -> tuple[qubit, bool]:
b = qsystem.measure_and_reset(q)
return q, b


@guppy(qsystem_functional)
@no_type_check
def zz_max(q1: qubit @ owned, q2: qubit @ owned) -> tuple[qubit, qubit]:
qsystem.zz_max(q1, q2)
return q1, q2


@guppy(qsystem_functional)
@no_type_check
def rz(q: qubit @ owned, angle: angle) -> qubit:
qsystem.rz(q, angle)
return q


@guppy(qsystem_functional)
@no_type_check
def measure(q: qubit @ owned) -> bool:
result = qsystem.measure(q)
return result


@guppy(qsystem_functional)
@no_type_check
def qfree(q: qubit @ owned) -> None:
qsystem.qfree(q)


@guppy(qsystem_functional)
@no_type_check
def reset(q: qubit @ owned) -> qubit:
qsystem.reset(q)
return q
72 changes: 7 additions & 65 deletions guppylang/std/quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

from guppylang.decorator import guppy
from guppylang.std._internal.compiler.quantum import (
HSERIES_EXTENSION,
MeasureReturnCompiler,
InoutMeasureCompiler,
RotationCompiler,
)
from guppylang.std._internal.util import quantum_op
Expand All @@ -33,17 +32,8 @@ def measure(self: "qubit" @ owned) -> bool:

@guppy
@no_type_check
def measure_return(self: "qubit") -> bool:
return measure_return(self)

@guppy
@no_type_check
def measure_reset(self: "qubit") -> bool:
"""Projective measure and reset without discarding the qubit."""
res = self.measure_return()
if res:
x(self)
return res
def project_z(self: "qubit") -> bool:
return project_z(self)

@guppy
@no_type_check
Expand Down Expand Up @@ -106,11 +96,6 @@ def tdg(q: qubit) -> None: ...
def sdg(q: qubit) -> None: ...


@guppy.hugr_op(quantum_op("ZZMax", ext=HSERIES_EXTENSION))
@no_type_check
def zz_max(q1: qubit, q2: qubit) -> None: ...


@guppy.custom(RotationCompiler("Rz"))
@no_type_check
def rz(q: qubit, angle: angle) -> None: ...
Expand Down Expand Up @@ -141,64 +126,21 @@ def toffoli(control1: qubit, control2: qubit, target: qubit) -> None: ...
def dirty_qubit() -> qubit: ...


@guppy.custom(MeasureReturnCompiler())
@guppy.custom(InoutMeasureCompiler())
@no_type_check
def measure_return(q: qubit) -> bool: ...
def project_z(q: qubit) -> bool: ...


@guppy.hugr_op(quantum_op("QFree"))
@no_type_check
def discard(q: qubit @ owned) -> None: ...


@guppy
@no_type_check
def measure(q: qubit @ owned) -> bool:
res = measure_return(q)
discard(q)
return res


@guppy
@no_type_check
def phased_x(q: qubit, angle1: angle, angle2: angle) -> None:
f1 = float(angle1)
f2 = float(angle2)
_phased_x(q, f1, f2)


@guppy
@guppy.hugr_op(quantum_op("MeasureFree"))
@no_type_check
def zz_phase(q1: qubit, q2: qubit, angle: angle) -> None:
f = float(angle)
_zz_phase(q1, q2, f)
def measure(q: qubit @ owned) -> bool: ...


@guppy.hugr_op(quantum_op("Reset"))
@no_type_check
def reset(q: qubit) -> None: ...


# ------------------------------------------------------
# --------- Internal definitions -----------------------
# ------------------------------------------------------


@guppy.hugr_op(quantum_op("PhasedX", ext=HSERIES_EXTENSION))
@no_type_check
def _phased_x(q: qubit, angle1: float, angle2: float) -> None:
"""PhasedX operation from the hseries extension.
See `guppylang.prelude.quantum.phased_x` for a public definition that
accepts angle parameters.
"""


@guppy.hugr_op(quantum_op("ZZPhase", ext=HSERIES_EXTENSION))
@no_type_check
def _zz_phase(q1: qubit, q2: qubit, angle: float) -> None:
"""ZZPhase operation from the hseries extension.
See `guppylang.prelude.quantum.phased_x` for a public definition that
accepts angle parameters.
"""
25 changes: 2 additions & 23 deletions guppylang/std/quantum_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,6 @@ def sdg(q: qubit @ owned) -> qubit:
return q


@guppy(quantum_functional)
@no_type_check
def zz_max(q1: qubit @ owned, q2: qubit @ owned) -> tuple[qubit, qubit]:
quantum.zz_max(q1, q2)
return q1, q2


@guppy(quantum_functional)
@no_type_check
def rz(q: qubit @ owned, angle: angle) -> qubit:
Expand Down Expand Up @@ -141,20 +134,6 @@ def toffoli(
return control1, control2, target


@guppy(quantum_functional)
@no_type_check
def phased_x(q: qubit @ owned, angle1: angle, angle2: angle) -> qubit:
quantum.phased_x(q, angle1, angle2)
return q


@guppy(quantum_functional)
@no_type_check
def zz_phase(q1: qubit @ owned, q2: qubit @ owned, angle: angle) -> tuple[qubit, qubit]:
quantum.zz_phase(q1, q2, angle)
return q1, q2


@guppy(quantum_functional)
@no_type_check
def reset(q: qubit @ owned) -> qubit:
Expand All @@ -164,6 +143,6 @@ def reset(q: qubit @ owned) -> qubit:

@guppy(quantum_functional)
@no_type_check
def measure_return(q: qubit @ owned) -> tuple[qubit, bool]:
b = quantum.measure_return(q)
def project_z(q: qubit @ owned) -> tuple[qubit, bool]:
b = quantum.project_z(q)
return q, b
Loading

0 comments on commit b0f041f

Please sign in to comment.