@guppy decorator

@guppylang.decorator.guppy

Registers a function for Guppy compilation.

from guppylang import guppy
from guppylang.std.quantum import h, qubit

@guppy
def plus_q() -> qubit:
   """Allocate and prepare a qubit in the |+> state"""
   q = qubit()
   h(q)
   return q
@guppy.comptime

Registers a function to be executed at compile-time during Guppy compilation, enabling the use of arbitrary Python features as long as they don’t depend on runtime values.

from guppylang import guppy
from guppylang.std.builtins import array

@guppy.comptime
def print_arrays(arr1: array[str, 10], arr2: array[str, 10]) -> None:
   for s1, s2 in zip(arr1, arr2):
      print(f"({s1}, {s2})")
@guppy.struct

Registers a class as a Guppy struct.

from guppylang import guppy

@guppy.struct
class MyStruct:
   field1: int
   field2: int

   @guppy
   def add_fields(self: "MyStruct") -> int:
      return self.field2 + self.field2
guppy.type_var(name, copyable=True, droppable=True)
Parameters:
  • name (str) – Name of the type variable.

  • copyable (bool) – Whether the type variable is copyable.

  • droppable (bool) – Whether the type variable is droppable.

Return type:

TypeVar

Creates a new type variable.

from guppylang import guppy

T = guppy.type_var("T")

@guppy
def identity(x: T) -> T:
   return x
guppy.nat_var(name)
Parameters:

name (str) – Name of the constant natural variable.

Return type:

TypeVar

Creates a new nat variable.

guppy.const_var(name, ty)
Parameters:
  • name (str) – Name of the constant type variable.

  • ty (str) – Type expression string.

Return type:

TypeVar

Creates a new const type variable.

@guppy.declare

Declares a Guppy function without defining it.

@guppy.overload(*funcs)
Parameters:

funcs (list[GuppyFunctionDefinition]) – Guppy function definitions to combine.

Collects multiple function definitions into one overloaded function.

Consider the following example:

@guppy.declare
def variant1(x: int, y: int) -> int: ...

@guppy.declare
def variant2(x: float) -> int: ...

@guppy.overload(variant1, variant2)
def combined(): ...

Now, combined may be called with either one float or two int arguments, delegating to the implementation with the matching signature:

combined(4.2)  # Calls `variant1`
combined(42, 43)  # Calls `variant2`

Note that the compiler will pick the first implementation with matching signature and ignore all following ones, even if they would also match. For example, if we added a third variant

@guppy.declare
def variant3(x: int) -> int: ...

@guppy.overload(variant1, variant2, variant3)
def combined_new(): ...

then a call combined_new(42) will still select the variant1 implementation 42 is a valid argument for variant1 and variant1 comes before variant3 in the @guppy.overload annotation.

guppy.constant(name, ty, value)
Parameters:
  • name (str) – Name of the constant.

  • ty (str) – Type expression string.

  • value (Value) – The value of the constant.

Adds a constant backed by a hugr.val.Value

@guppy.pytket(input_circuit)
Parameters:

input_circuit (Circuit) – The pytket circuit to load.

Backs a function declaration by the given pytket circuit. The declaration signature needs to match the circuit definition in terms of number of qubit inputs and measurement outputs.

There is no linearity checking inside pytket circuit functions. Any measurements inside the circuit get returned as bools, but the qubits do not get consumed and the pytket circuit function does not require ownership. You should either make sure you discard all qubits you know are measured during the circuit, or avoid measurements in the circuit and measure in Guppy afterwards.

Note this decorator doesn’t support passing inputs as arrays (use load_pytket instead).

from pytket import Circuit
from guppylang import guppy

circ = Circuit(1)
circ.H(0)
circ.measure_all()

@guppy.pytket(circ)
def guppy_circ(q: qubit) -> bool: ...

@guppy
def foo(q: qubit) -> bool:
   return guppy_circ(q)
guppy.load_pytket(name, input_circuit, *, use_arrays=True)
Parameters:
  • name (str) – The name of the Guppy function.

  • input_circuit (Circuit) – The pytket circuit to load.

  • use_arrays (bool) – Whether to use arrays for registers in the function definition.

Return type:

GuppyFunctionDefinition

Load a pytket Circuit as a Guppy function. By default, each qubit register is represented by an array input (and each bit register as an array output), with the order being determined lexicographically. The default registers are ‘q’ and ‘c’ respectively. You can disable array usage and pass individual qubits by passing use_arrays=False.

from pytket import Circuit
from guppylang import guppy

circ = Circuit(2)
reg = circ.add_q_register("extra_reg", 3)
circ.measure_register(reg, "extra_bits")

guppy_circ = guppy.load_pytket("guppy_circ", circ)

@guppy
def foo(default_reg: array[qubit, 2], extra_reg: array[qubit, 3]) -> array[bool, 3]:
   # Note that the default_reg name is 'q' so it has to come after 'e...'
   # lexicographically.
   return guppy_circ(extra_reg, default_reg)

Any symbolic parameters in the circuit need to be passed as a lexicographically sorted array (if arrays are enabled, else individually in that order) as values of type angle.

The function name is determined by the function variable you bind the load_pytket method call to, however the name string passed to the method should match this variable for error reporting purposes.

There is no linearity checking inside pytket circuit functions. Any measurements inside the circuit get returned as bools, but the qubits do not get consumed and the pytket circuit function does not require ownership. You should either make sure you discard all qubits you know are measured during the circuit, or avoid measurements in the circuit and measure in Guppy afterwards.

@guppylang.decorator.custom_guppy_decorator[source]

Decorator to mark user-defined decorators that wrap builtin guppy decorators.

Example:

@custom_guppy_decorator
def my_guppy(f):
    # Some custom logic here ...
    return guppy(f)

@my_guppy
def main() -> int: ...

If the custom_guppy_decorator were missing, then the @my_guppy annotation would not produce a valid guppy definition.