Quantum Operations

These examples cover Guppy features around measurement values, gate parameters, modifiers, and nearby helper operations.

Measurement objects

Source file: guppy_examples/guppy-features/supported/measurement-object.py

from typing import no_type_check

from guppylang import guppy
from guppylang.std.builtins import output, qubit
from guppylang.std.quantum import h, measure, x


@guppy
@no_type_check
def main() -> None:
    control = qubit()
    target = qubit()
    h(control)
    measurement = measure(control)

    if measurement:
        x(target)

    output("measurement_read", measurement.read())
    output("target", measure(target).read())

In Guppy v1, measure(q) returns a measurement object. It can be used as a conditional value, and the classical result should be passed to output by calling .read().

Angles

Source file: guppy_examples/guppy-features/supported/angles.py

from typing import no_type_check

from guppylang import guppy
from guppylang.std.angles import angle, pi
from guppylang.std.builtins import output, qubit
from guppylang.std.quantum import measure, rz


@guppy
@no_type_check
def main() -> None:
    q = qubit()
    theta = (pi / 2.0) + angle(0.25)
    rz(q, theta)
    output("angle", measure(q).read())

Dagger modifier

Source file: guppy_examples/guppy-features/supported/modifier-dagger.py

from typing import no_type_check

from guppylang import guppy
from guppylang.std.angles import pi
from guppylang.std.builtins import dagger, output, qubit
from guppylang.std.quantum import measure, rz, x


@guppy
@no_type_check
def main() -> None:
    target = qubit()

    with dagger():
        rz(target, pi / 4.0)
        x(target)

    output("dagger_target", measure(target).read())

Control modifier

Source file: guppy_examples/guppy-features/supported/modifier-control.py

import sys
from typing import no_type_check

from guppylang import array, guppy
from guppylang.std.builtins import control, output, qubit
from guppylang.std.quantum import collect_measurements, cx, h, measure, measure_array, x


@guppy
@no_type_check
def controlled_x(ctl: qubit, target: qubit) -> None:
    with control(ctl):
        x(target)


@guppy
@no_type_check
def double_controlled_x(ctl: array[qubit, 2], target: qubit) -> None:
    with control(ctl[0], ctl[1]):
        x(target)


@guppy
@no_type_check
def main() -> None:
    # single control
    ctl = qubit()
    target = qubit()
    h(ctl)
    controlled_x(ctl, target)
    output("control_target", measure(target).read())
    output("control_ctl", measure(ctl).read())

    # double control
    ctl2 = array(qubit(), qubit())
    for i in range(2):
        h(ctl2[i])
    trg2 = qubit()
    double_controlled_x(ctl2, trg2)
    output("control_target_2", measure(trg2).read())
    output("control_ctl2", collect_measurements(measure_array(ctl2)))

    # multi control, multi target
    ctlm = array(qubit() for _ in range(3))
    for i in range(3):
        h(ctlm[i])
    targets = array(qubit() for _ in range(3))
    with control(ctlm):
        h(targets[0])
        cx(targets[0], targets[1])
        x(targets[2])
        cx(targets[1], targets[2])

    output("targets", collect_measurements(measure_array(targets)))
    output("ctlm", collect_measurements(measure_array(ctlm)))


if __name__ == "__main__":
    sys.stdout.buffer.write(main.compile().to_bytes())

Control modifiers are supported when the controlled operation can be resolved during compilation.

Barrier

Source file: guppy_examples/guppy-features/supported/barrier.py

from typing import no_type_check

from guppylang import array, guppy, qubit
from guppylang.std.builtins import output
from guppylang.std.platform import barrier
from guppylang.std.quantum import discard_array, h, measure


@guppy
@no_type_check
def main() -> None:
    qbs = array(qubit() for _ in range(4))
    h(qbs[0])
    barrier(qbs[0])
    h(qbs[0])
    barrier(qbs)
    q0, q1, *qbs = qbs
    b = False
    a = measure(q0).read()
    if a:
        h(q1)
        b = measure(q1).read()
        if b:
            b = False
    else:
        b = measure(q1).read()

    output("a", a)
    output("b", b)
    discard_array(qbs)

Barriers accept individual qubits and qubit arrays. Passing any non-qubit value will cause QIR generation to fail.

from typing import no_type_check

from guppylang import array, guppy, qubit
from guppylang.std.builtins import output
from guppylang.std.platform import barrier
from guppylang.std.quantum import discard_array, h, measure


@guppy
@no_type_check
def main() -> None:
    qbs = array(qubit() for _ in range(4))
    h(qbs[0])
    barrier(qbs[0])
    h(qbs[0])
    barrier(qbs, 9)
    q0, q1, *qbs = qbs
    b = False
    a = measure(q0).read()
    if a:
        h(q1)
        b = measure(q1).read()
        if b:
            b = False
    else:
        b = measure(q1).read()

    output("a", a)
    output("b", b)
    discard_array(qbs)

Expected error:

Compilation failed: H-series barriers cannot contain non-qubit types

Memory swap

Source file: guppy_examples/guppy-features/supported/mem-swap.py

from typing import no_type_check

from guppylang import guppy
from guppylang.std.builtins import output
from guppylang.std.mem import mem_swap


@guppy
@no_type_check
def main() -> None:
    left = 1
    right = 2
    mem_swap(left, right)
    output("swap_left", left)
    output("swap_right", right)