Library structure and philosophy¶
Experimental releases¶
Any release before version 1.0.0 is experimental, and the API may change between releases. Pin the package version for reproducible projects and check the release notes before upgrading.
Guppy Algorithms is built on the Guppy language framework. If Guppy is new to you, start with the Guppy language guide for an introduction to the language, type system, and programming model.
The source tree separates Python code that builds an algorithm from the Guppy code that runs on quantum registers:
guppyalgos/
├── algorithms/
│ ├── amplitude_amplification/
│ ├── block_encoding/
│ ├── phase_estimation/
│ ├── select/
│ ├── state_preparation/
│ └── time_evolution/
├── errors/
├── primitives/
│ ├── arithmetic/
│ ├── gate_decompositions/
│ ├── measurement/
│ ├── pauli/
│ ├── rotations/
│ ├── state_preparation/
│ └── subroutines/
└── utils/
├── guppy/
└── python/
algorithms/contains higher-level, user-facing constructions, including amplitude amplification, phase estimation, and time evolution. An algorithm often starts from classical data, such as a Hamiltonian, so a Python builder or factory processes that data and constructs the Guppy program.primitives/contains small reusable components from which algorithms are assembled. Most are Guppy functions parameterized by register types and compile-time sizes; a few require Python-side construction.qftis one generic Guppy function that specializes to the compile-time width of its input register.fanout_basicandfanout_logshare the same typed interface, allowing an algorithm to choose a sequential or logarithmic-depth implementation.
gate_decompositions/contains implementations or close variants of gates also available in Guppy’s standard library; use it when an algorithm needs a particular decomposition rather than a standard gate invocation.subroutines/is a home for gate-like operations that act on whole registers but do not fit a more specific primitive category.errors/contains shared error definitions used to report invalid classical inputs or unsupported constructions consistently.utils/guppy/contains helpers usable inside Guppy programs, such as register utilities, whileutils/python/contains host-side helpers for building and checking algorithms before compilation.
Algorithms: build from classical data¶
At the user level, pass a Zixy Hamiltonian to trotter_first_order, then call
the resulting step from an ordinary Guppy function:
from guppylang import guppy
from guppylang.std.builtins import array
from guppylang.std.quantum import qubit
import zixy.qubit.pauli as zqp
from guppyalgos.algorithms.time_evolution.trotter import trotter_first_order
hamiltonian = zqp.RealTermSum.from_str(
"(-0.5, Z0 X1), (-0.1, X0 Z1)"
)
trotter_step = trotter_first_order(hamiltonian, n_state_qubits=2)
@guppy
def apply_one_trotter_step(state_qreg: array[qubit, 2]) -> None:
trotter_step(state_qreg, 0.1)
hamiltonianis classical Python data that determines the Pauli terms in the constructed step.trotter_stepis the returned Guppy function. It acts on the state register and takes a time step; each Pauli term uses the rotationangle(coefficient * time_step).
Primitives: specialize from Guppy types¶
QFT does not need a Python builder. Its register width is part of the Guppy type:
from guppylang import guppy
from guppylang.std.builtins import array
from guppylang.std.quantum import qubit
from guppyalgos.primitives.subroutines.qft import qft
@guppy
def apply_qft(qreg: array[qubit, 4]) -> None:
qft(qreg)
One generic
qftdefinition works for every compile-time widthn_qft. This is parametric polymorphism.Here, Guppy infers
n_qft = 4fromarray[qubit, 4]and builds the four-qubit version. This specialization is also called monomorphization.QFT has no algorithm-specific classical input; its circuit follows from the register type.
This split is a design principle rather than a hard rule: some algorithms are pure Guppy, and a small number of primitives require Python-side construction.