guppyalgos.primitives.state_preparation

Primitive state-preparation routines.

Functions

basis_rotation_implementation(mode_matrix[, ...])

Build a Guppy callable for a real mode-basis rotation.

dicke_nk(qs, k)

Prepare a Dicke state on a given register for k excitations.

ghz_state(q)

Build a GHZ state from $ket{0}$ using a log depth CX ladder.

phase_gradient(n_qubits[, convention, rz_method])

Prepare a phase gradient (Fourier) state on n_qubits qubits.

u_nk(qs, k)

Apply the unitary U_nk.

uniform_state(num_nonzero_amplitudes[, ...])

Prepare a uniform state over the first num_nonzero_amplitudes basis states.

Classes

Convention(*values)

Register convention for phase-gradient state preparation.

class guppyalgos.primitives.state_preparation.Convention(*values)

Register convention for phase-gradient state preparation.

Standard is the little-endian phase-gradient layout used by the Gidney-adder rotation algorithm to realize the normal positive incremented-angle rotation. Reciprocal uses the reciprocal register layout, with the same positive phase schedule assigned directly by qubit index.

Reciprocal = 1
Standard = 0
guppyalgos.primitives.state_preparation.basis_rotation_implementation(mode_matrix, elementary_rotation=None, elementary_phase_rz_method=<function rz>, atol=1e-10)

Build a Guppy callable for a real mode-basis rotation.

mode_matrix is an n x n real orthogonal matrix acting on modes or orbitals, not a 2**n x 2**n Hilbert-space unitary. A basis rotation is the mode/orbital transformation and its induced occupation-space unitary.

The decomposition uses nearest-neighbor Givens elimination in a QR-style scheme. It emits at most n * (n - 1) / 2 Givens rotations, up to n single-qubit phase corrections, and a global phase. The schedule is emitted serially; parallel circuit depth is not optimized.

The matrix has no angle units. NumPy computes schedule angles and the global phase in radians via arctan2 and numpy.angle. At the Guppy boundary, these values are converted to half-turns because Guppy’s angle values use half-turns. Consequently, injected Guppy rotation and phase functions receive half-turns, while the returned schedules use radians; the same conceptual angles therefore use two units across this boundary. The generated circuit implements the induced occupation-space unitary up to exp(-1j * global_phase).

Returns the callable, Givens schedule, single-qubit phase schedule, and global phase. elementary_phase_rz_method handles the phase schedule. The default Givens rotation uses the standard rz implementation; a supplied elementary_rotation may use a different RZ implementation.

Return type:

tuple[GuppyFunctionDefinition, list[tuple[int, int, float]], list[tuple[int, float]], float]

References

I. D. Kivlichan et al., “Quantum Simulation of Electronic Structure with Linear Depth and Connectivity,” Phys. Rev. Lett. 120, 110501 (2018). https://doi.org/10.1103/PhysRevLett.120.110501

guppyalgos.primitives.state_preparation.dicke_nk(qs, k)

Prepare a Dicke state on a given register for k excitations.

The implementation is based on https://arxiv.org/pdf/1904.07358v1. However, notice our construction is top to bottom instead of bottom to top, so the k qubits flipped are the first ones and not the last ones. Dicke states are symmetrical so the outcome is the same.

It relies on two building blocks, the unitaries U_nk and the Split and Cyclic Shift gates.

Parameters:
  • qs (array of qubits) – Register of qubits where to prepare the state.

  • k (int) – Number of excitations.

guppyalgos.primitives.state_preparation.ghz_state(q)

Build a GHZ state from \(\ket{0}\) using a log depth CX ladder.

Contains a filter to remove unnecessary gates from the usual log depth CX ladder as the input state is all 0, this reduces the gate count to the same as a linear ladder, while retaining log depth.

GHZ state on n-qubits is given by: \(\ket{GHZ} = (\ket{0 ... 0} + \ket{1 ... 1}) / √2\)

Parameters:

q (array[qubit, n]) – Array of qubits to prepare the GHZ state on.

Due to https://github.com/Quantinuum/guppylang/issues/2225, needs to be called on arrays of size > 1.

guppyalgos.primitives.state_preparation.phase_gradient(n_qubits, convention=Convention.Standard, rz_method=<function rz>)

Prepare a phase gradient (Fourier) state on n_qubits qubits.

The circuit applies a Hadamard gate followed by the positive phase schedule Rz(π / 2**k). With Convention.Reciprocal, this phase is applied to qubit k directly, producing the product state:

\[|\mathcal{F}\rangle = \bigotimes_{k=0}^{n-1} \frac{|0\rangle + e^{i\pi/2^k}|1\rangle}{\sqrt{2}}\]

This is an important resource state for rotation synthesis when used in phase-gradient addition circuits. The Rz synthesis method is invoked once per qubit and can be customized via the rz_method argument, matching the interface used in pauli_exp().

The same positive single-qubit phases are used in both conventions. Convention.Standard is little-endian: it reverses the phase schedule so qs[0] is the least-significant qubit expected by arithmetic-style phase-gradient kickback circuits. This is the convention to use with guppyalgos.primitives.rotations.RotationPhaseGradient to realize the normal positive incremented-angle rotation. Convention.Reciprocal assigns the positive phase π / 2**k directly to qs[k].

from guppyalgos.primitives.state_preparation.phase_gradient import (
    phase_gradient,
)
from guppylang.std.quantum import rz

prep = phase_gradient(4, rz_method=rz)
Parameters:
  • n_qubits (int) – Number of qubits in the register.

  • convention (Convention) – Register convention used to assign the phase schedule. Defaults to Convention.Standard.

  • rz_method (GuppyFunctionDefinition[(qubit, angle), None]) – Rz decomposition method to use for each qubit rotation. The callable must have signature (qubit, angle) -> None. Defaults to the standard guppy rz().

Returns:

A Guppy function that, given an array of n_qubits qubits initialized in the \(|0\rangle\) state, prepares the phase gradient state in-place.

Return type:

GuppyFunctionDefinition

guppyalgos.primitives.state_preparation.u_nk(qs, k)

Apply the unitary U_nk.

guppyalgos.primitives.state_preparation.uniform_state(num_nonzero_amplitudes, cnx_box=<function cnx>, comparator_box=<function comparator_ripple_cuccaro>, dagger=False)

Prepare a uniform state over the first num_nonzero_amplitudes basis states.

This unitary will act on ceil(log2(num_nonzero_amplitudes)) qubits.

The output state is given by:

\[\frac{1}{\sqrt{L}} \sum_{i=0}^{L-1} \ket{i}\]
where \(L\)= num_nonzero_amplitudes

This function prepares a uniform superposition state on the input qubits. The input qubits are assumed to be initialized to \(\ket{0}\) state. The function first checks if the number of non-zero amplitudes is equal to \(2^n\). If equal, a Hadamard transformation is applied. Otherwise, an amplitude amplification based circuit is used.

Parameters:
  • num_nonzero_amplitudes (int) – The number of non-zero amplitudes of the uniform state.

  • cnx_box (GuppyFunctionDefinition, optional) – The multi-controlled CNOT function. Defaults to cnx.

  • comparator_box (GuppyFunctionDefinition, optional) – The comparator function. Defaults to ripple_carry_subtractor.

  • dagger (bool) – Return the dagger of the state prep if True, only relevant for the case where num_nonzero_amplitudes is not a power of 2.

Returns:

A Guppy function that prepares the uniform state on ceil(log2(L)) qubits.

Return type:

GuppyFunctionDefinition

Notes

  • If num_nonzero_amplitudes is equal to \(2^n\), the function applies a Hadamard transformation to prepare the uniform state.

  • If num_nonzero_amplitudes is not a power of 2,

    additional ancilla qubits will be required for applying amplitude amplification. (minimum 1, but currently n+1)