Python API Reference
The object surface (PauliLCU, Walk, QSVT, Trotter, …)
is re-exported from the package root
(cudaq_algorithms.PauliLCU); the composable device kernels stay in their
module namespaces. Symbols are documented below at their defining module.
Block encodings
- class cudaq_algorithms.pauli_lcu.PauliLCU(hamiltonian, num_qubits=None, *, include_identity=True, coefficient_threshold=1e-12)
Bases:
objectBlock encoding of H / alpha via a linear combination of Pauli strings.
- Parameters:
hamiltonian (HamiltonianLike) – A
cudaq.SpinOperator, a mapping{"XZI...": coefficient}, or an iterable of(coefficient, word)pairs. Words use one I/X/Y/Z character per qubit, position = qubit index.num_qubits (int | None) – Optional; inferred from the input when omitted, validated against it when given.
include_identity (bool) – Whether identity words are retained inside the encoded operator (their sum is always reported as
constant_term).coefficient_threshold (float) – Terms with
|coefficient|below this are dropped.1 (num_ancilla is always at least)
ancilla (Hamiltonians get one idle)
uniformly (so every encoding works)
empty. (with Walk/QSVT and no flattened kernel argument is ever)
- property kernel_args: tuple[list[float], list[int], list[int], list[int], list[int]]
(angles, term_controls, term_ops, term_lengths, term_signs).
Escape hatch for composing the module-level kernels inside your own
@cudaq.kernel; the factory methods below capture these for you. Returns defensive copies.
- encode_kernel(state_prep=None)
A kernel applying the full block encoding.
Without
state_prep: a@cudaq.kernel(state)allocating the system register fromstateand the ancilla register (in|0...0>) after it. Withstate_prep(a(qubits: qview)kernel): a zero-argument kernel that allocates the system register in|0...0>, runsstate_prepon it, then applies the encoding.- Parameters:
state_prep (Kernel | None)
- Return type:
Kernel
- walk_kernel(power=1, state_prep=None)
A kernel running PREPARE, walk^power, UNPREPARE.
The all-zero-ancilla block of the result is T_power(-H/alpha) applied to the input state (Chebyshev polynomial of the walk block -H/alpha). Input modes as in
encode_kernel: acudaq.State-taking kernel, or a zero-argument kernel whenstate_prepis given.- Parameters:
power (int)
state_prep (Kernel | None)
- Return type:
Kernel
- prepare_kernel()
(ancilla: qview): PREPARE with this encoding’s angles.- Return type:
Kernel
- unprepare_kernel()
(ancilla: qview): PREPARE dagger with this encoding’s angles.- Return type:
Kernel
- apply_kernel()
(ancilla, system): the full block encoding U_A.- Return type:
Kernel
- controlled_apply_kernel()
(control_and_ancilla, system): U_A controlled by qubit 0.Uncontrolled PREPARE pairs wrap the controlled SELECT, so the circuit is the identity at control
|0>.- Return type:
Kernel
- walk_step_kernel()
(ancilla, system): one qubitization walk step W.- Return type:
Kernel
- adjoint_walk_step_kernel()
(ancilla, system): one adjoint walk step W†.- Return type:
Kernel
- controlled_walk_step_kernel()
(control_and_ancilla, system): controlled walk step.- Return type:
Kernel
- controlled_adjoint_walk_step_kernel()
(control_and_ancilla, system): controlled adjoint walk step.- Return type:
Kernel
- select_observable()
The odd-moment SELECT observable for this encoding.
BlockEncoding protocol hook; delegates to the module-level
select_observable.- Return type:
SpinOperator
- cudaq_algorithms.pauli_lcu.select_observable(encoding)
The SELECT operator
sum_i sign_i |i><i|_anc x P_ias an observable.LCU-specific: built from the encoding’s signed Pauli terms. Its expectation after PREPARE and p walk steps is the odd Chebyshev moment <T_{2p+1}(H/alpha)> (the BlockEncoding.select_observable hook).
- Parameters:
encoding (PauliLCU)
- Return type:
SpinOperator
- class cudaq_algorithms.block_encoding.BlockEncoding(*args, **kwargs)
Bases:
ProtocolA zero-flagged block encoding
U_Awith<0|_anc U_A |0>_anc = H / alpha.PauliLCUis the provided implementation; double-factorized or sparse-oracle encodings plug in by satisfying the same surface.- property num_ancilla: int
Number of ancilla (signal) qubits flagging the encoded block.
Consumers (
Walk,QSVT, the walk observables) requirenum_ancilla >= 1: the walk’s-H/alphasign comes from a reflection about the ancilla zero state, which is a no-op on an empty register.PauliLCUnormalizes single-term inputs to one idle ancilla to satisfy this uniformly.
- controlled_apply_kernel()
(control_and_ancilla: qview, system: qview): U_A controlled by qubit 0 of the combined register.- Return type:
- walk_step_kernel()
(ancilla: qview, system: qview): one qubitization walk step W (block encodes-H/alpha).- Return type:
- adjoint_walk_step_kernel()
(ancilla: qview, system: qview): one adjoint walk step W†.- Return type:
- controlled_walk_step_kernel()
(control_and_ancilla: qview, system: qview): controlled W.- Return type:
- controlled_adjoint_walk_step_kernel()
(control_and_ancilla: qview, system: qview): controlled W†.- Return type:
- select_observable()
The odd-moment observable as a
cudaq.SpinOperator.Measured after PREPARE and
pwalk steps (no UNPREPARE), its expectation is the odd Chebyshev moment<T_{2p+1}(H/alpha)>. The construction is encoding-specific (for an LCU it issum_i sign_i |i><i|_anc x P_i); the even-moment reflection observable2|0..0><0..0| - Ineeds only the register geometry, soWalkderives it without an encoding hook.- Return type:
Qubitization and QSVT
- class cudaq_algorithms.qubitization.Walk(encoding)
Bases:
objectQubitization walk over a block encoding.
Generic over the
BlockEncodingprotocol: encoding-specific circuits and the odd-moment observable are delegated to the injected encoding (PauliLCUis the provided implementation).Provides walk/adjoint-walk kernel factories and Chebyshev-moment measurement in the QEL even/odd convention. Requires
num_ancilla >= 1(PauliLCUalways satisfies this; the guard defends against degenerate foreign encodings). The encoding is fixed at construction — kernels and observables are cached per instance.- Parameters:
encoding (BlockEncoding)
- property encoding
kernels and observables are cached against it, so swapping it would serve stale circuits).
- Type:
The injected block encoding (read-only
- kernel(power=1, uncompute=True, state_prep=None)
PREPARE, W^power, optionally UNPREPARE.
Without
state_prepthe returned kernel takes onecudaq.Stateargument (the input state as data — the simulation-friendly form). Withstate_prep— a kernel with signature(qubits: cudaq.qview)— the returned kernel takes no arguments: it allocates the system register in|0...0>, runsstate_prepon it, and applies the walks.state_prepmust act only on that register, whose width isnum_system(a documented contract; not verifiable at factory time).
- adjoint_kernel(power=1, uncompute=True, state_prep=None)
PREPARE, (W†)^power, optionally UNPREPARE (see
kernel).
- roundtrip_kernel(power=1, state_prep=None)
PREPARE, W^power, (W†)^power, UNPREPARE — the identity, for tests.
- Parameters:
power (int)
state_prep (Kernel | None)
- Return type:
Kernel
- controlled_kernel(power=1, control_state=1, uncompute=True, state_prep=None)
Controlled walks over the system register.
Input modes as in
kernel: withoutstate_prepthe returned kernel takes onecudaq.Stateargument; withstate_prepit takes no arguments and prepares the system register itself (the injected prep runs once, uncontrolled, as in QPE). Either way the system register is followed by one register holding [control, ancillas] (the control cannot share a control set with a separate register in CUDA-Q Python). The control qubit is initialized tocontrol_state; with control|0>the circuit is the identity up to the (cancelling) PREPARE pair.
- controlled_roundtrip_kernel(power=1, control_state=1, state_prep=None)
Controlled W^power then controlled (W dagger)^power — identity.
- moment(ket, order, *, state_prep=None)
Measure the Chebyshev moment <T_order(H/alpha)>.
The input state is given either as
ket(array-like or an already-builtcudaq.State— the simulation-friendly form) or asstate_prep(a(qubits: cudaq.qview)preparation kernel composed into the measured circuit — the hardware-shaped form). Provide exactly one.
- cudaq_algorithms.qubitization.reflection_observable(encoding)
R =
2|0...0><0...0| - Ion the ancilla register.- Parameters:
encoding (BlockEncoding)
- Return type:
cudaq.SpinOperator
- class cudaq_algorithms.qsvt.QSVT(encoding)
Bases:
objectQuantum singular value transformation over a block encoding.
Generic over the
BlockEncodingprotocol: encoding-specific circuits are delegated to the injected encoding (PauliLCUis the provided implementation).- Parameters:
encoding (BlockEncoding)
- property encoding
kernels are cached against it, so swapping it would serve stale circuits).
- Type:
The injected block encoding (read-only
- kernel(sequence, convention=None, state_prep=None)
A kernel applying the phase/walk sequence.
sequencemay be a PhaseSequence or a plain list of phases (optionally withconvention="qsp"). Withoutstate_prepthe returned kernel takes onecudaq.Stateargument; withstate_prep— a(qubits: cudaq.qview)kernel — it takes no arguments and prepares the system register itself. The signal register is allocated in|0...0>after the system register.- Parameters:
sequence (PhaseSequence | Iterable[float])
convention (str | None)
state_prep (Kernel | None)
- Return type:
Kernel
- controlled_kernel(sequence, convention=None, control_state=1, state_prep=None)
A kernel applying the sequence controlled.
Input modes as in
kernel: acudaq.State-taking kernel, or a zero-argument kernel whenstate_prepis given (the injected prep runs on the system register only, uncontrolled). Either way the system register is followed by one register holding [control, signal] (a CUDA-Q Python control set cannot mix a bare qubit with a separate register). With control|0>the sequence is the identity.- Parameters:
sequence (PhaseSequence | Iterable[float])
convention (str | None)
control_state (int)
state_prep (Kernel | None)
- Return type:
Kernel
- class cudaq_algorithms.qsvt.PhaseSequence(phases, walk_directions=None, convention='qsvt')
Bases:
objectA validated QSVT/QSP phase sequence.
- Parameters:
phases (tuple[float, ...]) – d + 1 phase angles for a degree-d polynomial.
walk_directions (tuple[int, ...]) – Optional; one direction (‘forward’/’adjoint’ or 0/1) per walk, length d. Defaults to all forward.
convention (str) – “qsvt” (projector phases
diag(e^{i phi}, 1), the default) or “qsp” (Z-rotation phasesdiag(e^{i phi}, e^{-i phi}), the QSPPACK convention). qsp-tagged phases are converted automatically wherever a circuit is built;phasesalways stays raw.
- cudaq_algorithms.qsvt.recover_real_time_evolution(cos_state, sin_state, cos_phases, sin_phases)
Combine cosine/sine QSP components into
exp(-i H t)|psi>.cos_stateandsin_stateare good-subspace statevectors produced by running qsp-convention sequences through the QSVT circuit (which executes doubled projector phases); the per-sequence global phaseexp(i * sum(phases))is removed here. Valid for real Hamiltonians and real input states, where the cosine/sine parts live in the real/imaginary components.
- cudaq_algorithms.qsvt.FORWARD = 0
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
- cudaq_algorithms.qsvt.ADJOINT = 1
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
Trotter
Suzuki-Trotter Hamiltonian simulation.
Product-formula time evolution for Hamiltonians expressed as sums of Pauli strings: term extraction, host-side planning and ordering, resource estimation, and the circuit primitive itself.
The typical workflow constructs a Trotter object (term extraction,
validation, and ordering happen once) and either uses its kernel
factories or composes the apply_trotter primitive inside a custom
kernel:
from cudaq_algorithms import trotter
evolution = trotter.Trotter(hamiltonian)
kernel = evolution.kernel(time=0.8, steps=4, order=2) # @cudaq.kernel()
resources = evolution.resources(steps=4, order=2)
Identity terms: for H = c I + H', apply_trotter implements the
product formula for H' only. The omitted exp(-i c t) is an
unobservable global phase for one unconditioned evolution but a real
relative phase for controlled or interference-based algorithms;
identity_coefficient is reported on the Trotter object so callers
can account for it (the simulation helper sim_utils.evolve
reintroduces it host-side).
- cudaq_algorithms.trotter.HamiltonianLike
a
cudaq.SpinOperator(or a singlecudaq.SpinOperatorTermproduct), a{"XZI...": coefficient}mapping, or an iterable of(coefficient, word)pairs.- Type:
Accepted Hamiltonian input forms
alias of
SpinOperator|SpinOperatorTerm|Mapping[str,complex] |Iterable[tuple[complex,str]]
- class cudaq_algorithms.trotter.Trotter(hamiltonian, ordering=TrotterOrdering.PRESERVE_INPUT, *, coefficient_tolerance=1e-12)
Bases:
objectSuzuki-Trotter product formulas for a Pauli-sum Hamiltonian.
Term extraction, validation, and ordering happen once at construction (identity terms are split off into
identity_coefficient); the evolution parameterstime,steps, andorderare supplied per kernel request, mirroring the other primitives (Walk.kernel(power=...),QSVT.kernel(sequence)).The object is hardware-shaped: nothing here executes a simulator-only API (see
sim_utils.evolvefor statevector-based evolution).- Parameters:
hamiltonian (HamiltonianLike)
ordering (TrotterOrdering | str)
coefficient_tolerance (float)
- property identity_coefficient: float
Sum of identity-term coefficients (not realizable in circuit).
- property ordering: TrotterOrdering
Term-ordering strategy fixed at construction.
- kernel(time, steps=1, order=2, state_prep=None)
Return a
@cudaq.kernel()applying the product formula.(
Anybecause CUDA-Q exposes no stable public Python type for compiled kernel objects.)The kernel allocates
num_qubitsqubits in|0...0>, optionally runsstate_prep(a kernel with signature(qubits: cudaq.qview)) on them, and applies theorder-order formula fortimeoverstepssteps — with or withoutstate_prepthe result takes no arguments and is directly sampleable.state_prepmust act only on the register it is handed (widthnum_qubits, arriving in|0...0>). The identity phase is not included (it cannot be, in a circuit); trackidentity_coefficientwhen it matters.
- state_kernel(time, steps=1, order=2)
Return a
@cudaq.kernel(state)evolving an arbitrary state.Same validated product formula as
kernel(), but the register is allocated from acudaq.Stateargument instead of|0...0>— the input-loading pathsim_utils.evolveuses. Both factories share validation and marshaling through_prepared_args.The supplied state must have dimension
2**num_qubits:sim_utils.evolvechecks this; direct callers are responsible for it themselves (the identity-only variant cannot detect a mismatch).
- resources(steps, order)
Resource estimate for
stepssteps of theorderformula.Both parameters are required so the estimate can never silently describe a different circuit than the kernel you built.
- Parameters:
- Return type:
- class cudaq_algorithms.trotter.TrotterOrdering(*values)
Bases:
EnumTerm-ordering strategies for the product formula.
PRESERVE_INPUTkeeps the extraction order;COEFFICIENT_MAGNITUDE_DESCENDINGapplies the largest-magnitude terms first, a common heuristic for reducing Trotter error.
- class cudaq_algorithms.trotter.TrotterResourceEstimate(num_terms, steps, order, pauli_rotations, estimated_cx_count, identity_coefficient)
Bases:
objectLightweight circuit-cost summary for a Trotter sequence.
estimated_cx_countis a decomposition proxy: two CNOTs per additional non-identity Pauli in each rotation.
- cudaq_algorithms.trotter.estimate_trotter_resources(coefficients, words, steps, order, identity_coefficient=0.0)
Return a lightweight resource estimate for a Trotter sequence.
- cudaq_algorithms.trotter.make_trotter_terms(hamiltonian, coefficient_tolerance=1e-12)
Return flattened terms for the Suzuki-Trotter circuit primitive.
Returns
(coefficients, words, identity_coefficient, num_qubits)wherewordsare padded plain strings: readable, comparable, and accepted directly aslist[cudaq.pauli_word]kernel arguments. (Only kernel-captured words need explicitcudaq.pauli_wordconversion, whichTrotter.kernelperforms internally.)coefficient_tolerancefilters term magnitudes only: terms with|coefficient|below it (and exactly-zero terms regardless of it) are dropped — they would emit zero-angle rotations and inflate resource estimates. It does not affect complex-coefficient validation, which is fixed package-wide (see_real_coefficient).
Preprocessing
Chemistry-input bridges between classical tensors and qubit Hamiltonians.
Connects the double-factorization preprocessing to the quantum primitives:
chemist-notation spatial integrals (the form the DF module consumes and
reconstructs) are spin-expanded and passed through the fermion
subpackage’s Jordan-Wigner transform, yielding a cudaq.SpinOperator
ready for PauliLCU/Walk/QSVT.
spin_orbital_tensors is pure NumPy and always importable and usable.
qubit_hamiltonian additionally uses fermion.jordan_wigner (imported
lazily); importing this module never raises, and if fermion is
unavailable the ImportError surfaces when qubit_hamiltonian is
called, not at import.
- cudaq_algorithms.chemistry.from_fcidump(contents)
Parse FCIDUMP contents into chemist-notation spatial integrals.
Takes the integral data as a string – the text of the file, already read – not a path; the caller does the file I/O:
one_body, eri, core = from_fcidump(Path("mol.fcidump").read_text())
Keeping the parse pure (no file access) lets callers and tests inject the integrals directly. Returns
(one_body, eri, core_energy): the(n, n)core Hamiltonian, the dense(n, n, n, n)chemist-notation(pq|rs)two-electron tensor (all eight symmetry partners of each stored record populated), and the scalar core/constant energy – the(one_body, eri, core_energy)triple, in the exact conventionqubit_hamiltonianand the block encodings consume:one_body, eri, core = from_fcidump(text) hamiltonian = qubit_hamiltonian(one_body, eri, scalar_offset=core)
FCIDUMP indices are Fortran 1-based; a
value i j k lrecord with all ofi,j,k,lnonzero is a two-electron integral, withk == l == 0a one-electron integralh_ij(its transpose is filled too), and with all indices zero the core energy.Only real (RHF/ROHF-style) FCIDUMP files are supported; unrestricted variants (Molpro’s
IUHF=1or Psi4’sUHF=.TRUE.) store a spin-resolved integral set with a different index symmetry and are rejected up front by a header guard.
- cudaq_algorithms.chemistry.spin_orbital_tensors(one_body, eri, *, validate_symmetry=True)
Spin-expand chemist-notation spatial integrals.
one_bodyis the(n, n)core Hamiltonian anderithe(n, n, n, n)chemist-notation(pq|rs)two-electron tensor over real spatial orbitals — the exact convention the double-factorization module documents. Returns(one_body_so, two_body_so)over2nspin orbitals (interleaved spins:2pup,2p + 1down), wheretwo_body_so[p, q, r, s]is the coefficient ofa^dag_p a^dag_q a_r a_sas consumed byfermion.jordan_wigner.erimust obey the real-orbital chemist permutation symmetry ((pq|rs) = (qp|rs) = (pq|sr) = (rs|pq)and their compositions) — this is what makes the resulting qubit Hamiltonian Hermitian, and it holds for reconstructed DF integrals and mean-field integrals. It is checked by default; passvalidate_symmetry=Falseto skip the check (e.g. for genuinely complex integrals, whose symmetry differs).
- cudaq_algorithms.chemistry.qubit_hamiltonian(one_body, eri, *, scalar_offset=0.0, tolerance=1e-12, validate_symmetry=True)
Qubit Hamiltonian (
cudaq.SpinOperator) from chemist integrals.Spin-expands the spatial integrals (see
spin_orbital_tensors, whoseerisymmetry precondition andvalidate_symmetryflag apply here too) and applies the Jordan-Wigner transform.scalar_offsetis added as an identity term (e.g. the nuclear repulsion energy);toleranceprunes negligible terms inside the transform.Combined with the double-factorization module this closes the classical-to-quantum loop:
factorization = compressed_double_factorization(eri, num_leaves=T) h_truncated = qubit_hamiltonian(one_body, reconstruct_eri(factorization)) encoding = PauliLCU(h_truncated) # -> Walk / QSVT
- cudaq_algorithms.chemistry.from_pyscf(mean_field)
Chemist
(pq|rs)MO integrals + nuclear repulsion from PySCF.mean_fieldis a converged restricted mean field (e.g. the result ofpyscf.scf.RHF(mol).run()). Returns(one_body, eri, nuclear_repulsion)in the molecular-orbital basis and chemist notation – exactly the argumentsqubit_hamiltonian()expects (passnuclear_repulsionas itsscalar_offset).Restricted (single
mo_coeffmatrix) references only; the spin expansion downstream assumes one spatial set shared by both spins.
- cudaq_algorithms.chemistry.from_psi4(wavefunction)
Chemist
(pq|rs)MO integrals + nuclear repulsion from Psi4.wavefunctionis a converged restricted wavefunction, e.g. the second return value ofpsi4.energy("scf", return_wfn=True). Returns(one_body, eri, nuclear_repulsion)in the molecular-orbital basis and chemist notation – identical in meaning and convention tofrom_pyscf(), so either drivesqubit_hamiltonian()unchanged.Restricted references only (uses
Ca);mo_erialready returns the chemist(pq|rs)ordering, matching the PySCF path.The wavefunction must be computed in C1 symmetry (
symmetry c1in the Psi4 geometry). The extraction readsCaas a single dense block, so an irrep-blocked (higher-symmetry) wavefunction is rejected.
Fermion-to-qubit transforms (pure Python, no compiled extension).
- cudaq_algorithms.fermion.jordan_wigner(one_body_or_two_body, two_body=None, scalar_offset=0.0, tolerance=1e-15)
Jordan-Wigner transform of fermionic integrals to a qubit operator.
Accepts an
(n, n)one-body tensor, optionally with an(n, n, n, n)two-body tensor, or a two-body tensor alone; entries are the coefficients ofadag_i a_jandadag_i adag_j a_k a_lovernspin orbitals.scalar_offsetis added as an identity term; input entries and compiled terms with magnitude belowtoleranceare dropped. Returns acudaq.SpinOperator.
- cudaq_algorithms.fermion.bravyi_kitaev(one_body_or_two_body, two_body=None, scalar_offset=0.0, tolerance=1e-15)
Bravyi-Kitaev transform of fermionic integrals to a qubit operator.
Same input conventions as
jordan_wigner; the qubits store Fenwick-tree partial sums of the occupations, giving O(log n)-weight Pauli words. Returns acudaq.SpinOperator.Migration note: the two-body tensor is compiled literally, entry by entry as
V[i,j,k,l] adag_i adag_j a_k a_l— identical tojordan_wigner. The retired compiled binding instead antisymmetrized the tensor internally before transforming; matchingjordan_wignerhere repairs a prior JW/BK inconsistency. A caller who passed a raw, non-antisymmetrized (e.g. chemist-ordered) two-body tensor and relied on that internal antisymmetrization must now antisymmetrize the input themselves, or they will silently get a different operator.
Double factorization of two-electron integrals (X-DF and C-DF).
Explicit (X-DF) and compressed (C-DF) double factorization following Cohn, Motta, and Parrish, PRX Quantum 2, 040352 (2021) (arXiv:2104.08957). Heavy linear algebra runs on the NVIDIA math libraries (cuSOLVER / cuBLAS via CuPy) when a GPU is available, with a NumPy/SciPy fallback selected automatically.
- class cudaq_algorithms.double_factorization.DoubleFactorization(num_orbitals, leaf_rotations, leaf_cores, method, first_factorization=None, leaf_weights=None)
Bases:
objectResult of a double factorization of the two-electron integrals.
leaf_rotations[t]is the orthogonal matrixU^t(shape(num_orbitals, num_orbitals)) andleaf_cores[t]is the symmetric coreZ^tfor leaft.methodis"X-DF"or"C-DF".- Parameters:
- cudaq_algorithms.double_factorization.explicit_double_factorization(eri, threshold=1e-08, max_num_leaves=None, second_factor_threshold=0.0, first_factorization='cholesky', backend='auto')
Explicit double factorization (X-DF).
First factorization of the ERI supermatrix
(pq|rs) = sum_t L^t_pq L^t_rsinto symmetric leavesL^t:first_factorization="cholesky"(default) – pivoted Cholesky of the positive-semidefinite ERI matrix. Rank-revealing: it keeps leaves while the residual-diagonal pivot exceedsthreshold(the numerical null space terminates it), so it stops at the true factorization rank.first_factorization="eigendecomposition"– symmetric eigendecomposition(pq|rs) = sum_t lambda_t V^t_pq V^t_rskeeping|lambda_t| > threshold. Required for indefinite inputs; the ERI is PSD so Cholesky is preferred.
max_num_leavescaps the leaf count. Second factorization: each symmetric leaf is eigendecomposed,L^t = U^t diag(gamma^t) (U^t)^T, giving the rank-one coreZ^t = outer(gamma^t, gamma^t)(scaled bylambda_tin the eigendecomposition case).second_factor_thresholdoptionally zeros smallgamma^t_k(importance-weighted, matching OpenFermion’s convention). On the eigendecomposition path the importance includes|lambda_t|, so both paths compare the same absolute quantity – the mode’s contribution to the core one-norm; on the Cholesky path the pivot scale is already carried by the leaf vector’s norm.Returns a
DoubleFactorizationwith NumPy arrays.
- cudaq_algorithms.double_factorization.compressed_double_factorization(eri, num_leaves, max_iterations=2000, tolerance=1e-10, regularization=0.0, inner_solver='lstsq', cg_tolerance=1e-10, cg_max_iterations=None, cg_warm_start=True, cg_optimization_tolerance=None, initial_generators=None, backend='auto')
Compressed double factorization (C-DF) by least-squares optimization.
Minimizes
O = 1/2 || eri - sum_t U^t Z^t (U^t)^T (congruence) ||_F^2over a fixed number of leaves. Uses the two-step scheme of arXiv:2104.08957: the leaf rotations are parameterized asU^t = exp(X^t)with antisymmetricX^tand optimized with L-BFGS (warm-started from X-DF), while the symmetric coresZ^tare solved exactly in closed form at each step.regularization(rho) enables RC-DF (arXiv:2212.07957, Eq. 17): the L2 penaltyrho * sum_{t,k,l} (Z^t_kl)^2is added to the objective and, crucially, folded into the inner core solve as a ridge term. It shrinks the cores – lowering the Hamiltonian one-normlambdaand the measurement variance – and conditions the inner system.rhois an absolute coefficient (its useful scale depends on the integral magnitude; the paper uses ~1e-6 to 1e-3).rho = 0reproduces plain C-DF.inner_solverselects how the cores are solved each step:"lstsq"(default) forms an explicit design matrix, while"cg"is the matrix-free conjugate-gradient solve (RC-DF Eqs. 25-30) that avoids then^4-row design matrix and scales to large orbital counts.cg_toleranceandcg_max_iterationscontrol the CG solve.For
inner_solver="cg"two accelerators cut the per-step CG cost without changing the final accuracy:cg_warm_start(defaultTrue) seeds each step’s CG from the previous step’s cores – which move slowly between L-BFGS steps – andcg_optimization_tolerance(defaultmax(cg_tolerance, 1e-6)) solves the in-loop systems only loosely (an inexact inner solve; the gradient need only be approximate by the envelope theorem) while the single final solve is tightened tocg_tolerance.Returns a
DoubleFactorizationwith NumPy arrays.- Parameters:
- Return type:
- cudaq_algorithms.double_factorization.reconstruct_eri(factorization)
Reconstruct the chemist-notation ERI tensor from a factorization.
- Parameters:
factorization (DoubleFactorization)
- Return type:
- cudaq_algorithms.double_factorization.factorization_error(eri, factorization)
Frobenius norm of the ERI reconstruction residual.
- Parameters:
eri (ArrayLike)
factorization (DoubleFactorization)
- Return type:
- cudaq_algorithms.double_factorization.modified_one_body_integrals(one_body, eri)
Return the DF-corrected one-body matrix
kappa_pq = h_pq - 1/2 sum_r (pr|qr)(Eq. 3 of arXiv:2104.08957), used when assembling the full double-factorized Hamiltonian from the two-body factorization.- Parameters:
one_body (ArrayLike)
eri (ArrayLike)
- Return type:
- cudaq_algorithms.double_factorization.double_factorization_one_norm(factorization, one_body_eigenvalues, convention='lcu')
One-norm
lambdaof the double-factorized Hamiltonian (RC-DF, arXiv:2212.07957), used to assess factorization quality.convention="lcu"(Eq. 13) – the LCU / Pauli-rotation normsum_k |F_k| + sum_t (sum_{k<l} |Z^t_kl| + 1/4 sum_k |Z^t_kk|).convention="burg"– the qubitization norm in the standard von Burg/Lee form: with each core eigendecomposed asZ^t = sum_i lambda^t_i v^t_i (v^t_i)^T,sum_k |F_k| + 1/4 sum_t sum_i |lambda^t_i| (sum_k |v^t_ki|)^2. (A factorizationZ = W W^TleavesWfree up to a right orthogonal gauge, and the column-norm formula is not gauge invariant; the eigenfactor is the standard, gauge-fixed choice and reduces to RC-DF Eq. 15 / von Burg’s(1/4)(sum_k |gamma_k|)^2for rank-one cores.)one_body_eigenvaluesare the diagonal one-body (Fock-like) eigenvalues.- Parameters:
factorization (DoubleFactorization)
one_body_eigenvalues (ArrayLike)
convention (str)
- Return type:
- cudaq_algorithms.double_factorization.cupy_gpu_available()
Return True when CuPy is importable and at least one GPU is visible.
- Return type:
- cudaq_algorithms.double_factorization.resolve_backend(backend='auto', problem_size=None, gpu_min_size=0)
Return
(array_module, name)for the requested backend."auto"selects CuPy when a GPU is available and the problem is large enough to amortize GPU launch/sync overhead – i.e.problem_size(the orbital countn) is at leastgpu_min_size– otherwise NumPy. With noproblem_sizehint it keeps the legacy behavior: CuPy whenever a GPU is present."cupy"/"numpy"force the backend regardless of size.
State preparation
State-preparation kernels and operator pools (pure Python).
Same API as the former compiled bindings: the uccsd, uccgsd,
upccgsd, and ceo device kernels are @cudaq.kernel functions
composable from user kernels, and the excitation/pool helpers run on the
host with cudaq.spin algebra. hartree_fock /
hartree_fock_occupation prepare the reference determinant (closed
shell, or open shell via make_hartree_fock_occupation), and
fixed_parameter_ucc / hartree_fock_ucc_kernel apply an arbitrary
operator pool at fixed, non-variational amplitudes on top of it. The
Givens-rotation Slater-determinant kernels and schedule helpers
(_givens) follow the same split: composable device kernels plus
host-side planning.
Error-type convention: the two error cases the compiled bindings
defined keep their historical RuntimeError (odd qubit count and
odd-electrons-at-spin-0 in get_uccsd_excitations); every guard
added in the pure implementation raises ValueError. Note also that
the CEO helpers take num_orbitals in spatial orbitals (the pool
acts on 2 * num_orbitals qubits), matching the compiled API.
- cudaq_algorithms.stateprep.get_uccsd_excitations(num_qubits, num_electrons, spin=0)
Enumerate UCCSD excitations for the interleaved spin-orbital layout.
Returns
(singles_alpha, singles_beta, doubles_mixed, doubles_alpha, doubles_beta)as lists of index lists, in the C++ enumeration order (which fixes the parameter order of theuccsdkernel).
- cudaq_algorithms.stateprep.get_num_uccsd_parameters(num_qubits, num_electrons, spin=0)
Number of UCCSD ansatz parameters (one per excitation).
- cudaq_algorithms.stateprep.get_uccgsd_pauli_lists(num_qubits, only_singles=False, only_doubles=False)
UCCGSD pool as (pauli word groups, coefficient groups).
- cudaq_algorithms.stateprep.get_upccgsd_pauli_lists(num_qubits, only_doubles=False)
UpCCGSD pool as (pauli word groups, coefficient groups).
- cudaq_algorithms.stateprep.get_ceo_pauli_lists(num_orbitals)
CEO pool as (pauli word groups, coefficient groups).
- cudaq_algorithms.stateprep.get_fixed_parameter_ucc_pauli_lists(operator_pool, num_qubits, coefficient_tolerance=1e-12)
Any operator pool as (Pauli word groups, coefficient groups).
Like the pool-specific
get_*_pauli_listshelpers, but for an arbitrary pool (e.g.make_uccsd_operator_pool): one group per pool operator, in pool order, ready for thefixed_parameter_ucckernel. Terms with|coefficient| <= coefficient_toleranceare dropped (they would waste identity rotations); coefficients with an imaginary part above the tolerance are rejected —exp_pauliangles are real.
- cudaq_algorithms.stateprep.make_uccsd_operator_pool(num_qubits, num_electrons, spin=0)
One spin operator per UCCSD excitation, in excitation order.
- cudaq_algorithms.stateprep.make_uccgsd_operator_pool(num_qubits, only_singles=False, only_doubles=False)
Generalized singles and doubles over all qubit pairs/quadruples.
- cudaq_algorithms.stateprep.make_upccgsd_operator_pool(num_qubits, only_doubles=False)
Spin-preserving singles plus paired (same-spatial-orbital) doubles.
- cudaq_algorithms.stateprep.make_ceo_operator_pool(num_orbitals)
Coupled-exchange-operator pool (arXiv:2407.08696 conventions).
- cudaq_algorithms.stateprep.make_hartree_fock_occupation(num_qubits, num_electrons, spin=0)
Occupied spin-orbital indices of the Hartree-Fock reference.
spin == 0(closed shell): the contiguous set{0, ..., num_electrons - 1}.spin > 0(open shell): alpha electrons on even spin orbitals and beta on odd, matchingget_uccsd_excitationsso the determinant lines up with a fixed-parameter UCCSD pool built at the same spin (e.g. 4 electrons at spin 2 occupy{0, 1, 2, 4}, not{0, 1, 2, 3}).
- cudaq_algorithms.stateprep.validate_hartree_fock_occupation(num_qubits, occupied_orbitals)
Reject out-of-range, duplicate, or non-integral orbital indices.
- cudaq_algorithms.stateprep.validate_fixed_parameter_ucc(num_qubits, parameters, pauli_words, coefficients)
Validate grouped fixed-parameter UCC data against
num_qubits.Pauli words given as strings are checked for length and alphabet;
cudaq.pauli_wordobjects expose no accessor and are trusted (theget_*_pauli_listshelpers build them at the right width).
- cudaq_algorithms.stateprep.estimate_hartree_fock_resources(num_qubits, num_electrons, spin=0)
Resource estimate for the canonical Hartree-Fock reference.
- Return type:
- cudaq_algorithms.stateprep.estimate_hartree_fock_occupation_resources(num_qubits, occupied_orbitals)
Resource estimate for an explicit-occupation reference.
- Return type:
- cudaq_algorithms.stateprep.estimate_fixed_parameter_ucc_resources(num_qubits, pauli_words)
Resource estimate for a fixed-parameter UCC product.
- Return type:
- cudaq_algorithms.stateprep.hartree_fock_ucc_kernel(num_qubits, parameters, pauli_words, coefficients, *, num_electrons=None, spin=0, occupied_orbitals=None)
A
(qubits: qview)kernel: Hartree-Fock reference + UCC product.Provide exactly one of
num_electrons(with optionalspinfor an open-shell reference) or explicitoccupied_orbitals. The returned kernel expects anum_qubits-wide register in|0...0>and is directly injectable as astate_prepkernel (e.g. intoPauliLCU.encode_kernel). The grouped data is flattened into per-rotation angles before capture — nested lists cannot be captured by Python kernels.
- class cudaq_algorithms.stateprep.HartreeFockResourceEstimate(num_qubits, num_electrons, num_x_gates)
Bases:
objectCircuit cost of a Hartree-Fock reference preparation.
- class cudaq_algorithms.stateprep.FixedParameterUccResourceEstimate(num_qubits, num_excitations, num_pauli_rotations, max_pauli_rotations_per_excitation)
Bases:
objectCircuit cost of a fixed-parameter UCC product (Pauli rotations).
- class cudaq_algorithms.stateprep.GivensRotation(first_orbital, second_orbital, theta, phase=0.0)
Bases:
objectOne adjacent Givens rotation between two orbitals.
phaseis the relative phase applied after the rotation (exp(i * phase * n_second)); it is 0 for real schedules.
- class cudaq_algorithms.stateprep.GivensRotationSchedule(num_spin_orbitals, num_electrons, is_complex=False, rotations=<factory>, final_phases=<factory>)
Bases:
objectA Givens rotation sequence preparing a Slater determinant.
rotationsare in application order (the reverse of the elimination order).final_phasesholds one phase per electron, applied to the occupied qubits before the rotations; it is all-zero for real schedules.
- class cudaq_algorithms.stateprep.GivensResourceEstimate(num_spin_orbitals, num_electrons, num_givens_rotations, num_exp_pauli_calls, num_phase_rotations, two_qubit_gate_count_proxy, depth_proxy)
Bases:
objectLightweight circuit-cost summary for a Givens schedule.
num_spin_orbitalsandnum_electronsecho the schedule.num_exp_pauli_callscounts the two-qubitexp_paulirotations (two per Givens rotation);num_phase_rotationscounts the single-qubitrzgates of a complex preparation (one per rotation plus one per electron). The proxies are decomposition-independent upper bounds, not transpiled gate counts.
- cudaq_algorithms.stateprep.slater_determinant_kernel(schedule)
A
(qubits: qview)kernel preparing the schedule’s determinant.The returned kernel expects a
schedule.num_spin_orbitals-wide register in|0...0>and is directly injectable as astate_prepkernel (e.g. intoPauliLCU.encode_kernel). It dispatches onschedule.is_complexto theslater_determinant/complex_slater_determinantkernel path. The schedule is flattened into plain index/angle/phase arrays before capture — nested structures marshal as kernel arguments but cannot be closure-captured by Python kernels.- Parameters:
schedule (GivensRotationSchedule)
- cudaq_algorithms.stateprep.make_givens_rotation_schedule(orbital_coefficients, tolerance=1e-12)
Build the Givens rotation schedule preparing a Slater determinant.
orbital_coefficientsis a (num_spin_orbitals x num_electrons) matrix (numpy array or nested lists) whose orthonormal columns are the occupied orbitals. Real and complex inputs dispatch automatically (a complex dtype routes complex even when all values are real). For interleaved-spin systems the matrix rows must follow the package’s alpha (even) / beta (odd) spin-orbital ordering, so the prepared determinant composes withhartree_fock_occupationreferences and the UCCSD excitation conventions built at the same spin.- Return type:
- cudaq_algorithms.stateprep.validate_givens_rotation_schedule(schedule)
Validate a schedule against the state-preparation kernel contract.
make_givens_rotation_scheduleoutput always passes; this guards hand-built schedules (the kernels themselves cannot raise).- Parameters:
schedule (GivensRotationSchedule)
- cudaq_algorithms.stateprep.get_givens_rotation_indices(schedule)
Flattened (first, second) orbital pairs, two entries per rotation.
- Parameters:
schedule (GivensRotationSchedule)
- Return type:
- cudaq_algorithms.stateprep.get_givens_rotation_angles(schedule)
Rotation angles in application order.
- Parameters:
schedule (GivensRotationSchedule)
- Return type:
- cudaq_algorithms.stateprep.get_givens_rotation_phases(schedule)
Relative phases in application order (all zero for real schedules).
- Parameters:
schedule (GivensRotationSchedule)
- Return type:
- cudaq_algorithms.stateprep.estimate_givens_resources(schedule)
Resource estimate for preparing a schedule’s Slater determinant.
- Parameters:
schedule (GivensRotationSchedule)
- Return type:
Simulation utilities
Simulation-only helpers.
Everything here depends on statevector access (cudaq.get_state /
postselection slicing), which only exists on simulators. The module ships
with the package as a clearly-labeled companion, but it is not part of the
hardware-shaped API: the library classes (encodings, kernel factories,
observables, Walk.moment via cudaq.observe) never execute
get_state.
- cudaq_algorithms.sim_utils.state_from(ket)
Build a cudaq.State from array data at the current target’s precision.
fp32 simulators (e.g. the default
nvidiatarget) reject complex128 input (“[sim-state] invalid data precision”); cudaq.complex() reports the dtype the active target expects.- Return type:
State
- cudaq_algorithms.sim_utils.good_subspace(encoding, state)
Postselect the all-zero-ancilla block of a simulated statevector.
The kernel factories allocate the system register first, so with CUDA-Q’s little-endian statevector order (q[0] = least-significant bit) the good subspace is the first contiguous block of 2**num_system amplitudes.
- Parameters:
encoding (PauliLCU)
state (ArrayLike)
- Return type:
NDArray[np.complex128]
- cudaq_algorithms.sim_utils.action(encoding, ket)
Return (H/alpha)|ket> by simulating the encoding and postselecting.
Multiply by
encoding.alphato recover H|ket>.- Parameters:
encoding (PauliLCU)
ket (ArrayLike)
- Return type:
NDArray[np.complex128]
- cudaq_algorithms.sim_utils.transform(transformer, ket, sequence, convention=None)
Return the good-subspace state after a QSVT sequence.
For an eigenstate of H with eigenvalue lambda the result is
p(lambda / alpha)times the input, wherepis the polynomial the phase sequence implements.- Parameters:
transformer (QSVT)
ket (ArrayLike)
sequence (PhaseSequence | Iterable[float])
convention (str | None)
- Return type:
NDArray[np.complex128]
- cudaq_algorithms.sim_utils.evolve(evolution, ket, time, steps=1, order=2, include_identity_phase=True)
Simulate a Trotter evolution on
ket; return the evolved statevector.Unlike the circuit primitive, this can reintroduce the identity phase
exp(-i * identity_coefficient * time)(on by default), so the result approximates the fullexp(-i H t)|ket>.Delegates to
Trotter.state_kernel— the same validation (finite time, positive integral steps, order in {1, 2, 4}) and marshaling asTrotter.kernel, raisingValueErrorfor invalid parameters instead of silently returning an unevolved state.
- cudaq_algorithms.common_kernels.state_from(ket)
Build a cudaq.State from array data at the current target’s precision.
fp32 simulators (e.g. the default
nvidiatarget) reject complex128 input (“[sim-state] invalid data precision”); cudaq.complex() reports the dtype the active target expects.- Return type:
State