UCJ¶
- class UCJ(variant, diag_coulomb_mats, orbital_rotations, *, final_orbital_rotation=None)¶
Bases:
FermionicGateImplements the (local) unitary cluster Jastrow ((L)UCJ) ansatz.
A unitary cluster Jastrow operator has the form
\[\left(\prod_{k=1}^{L} \mathcal{U}_k\, e^{i \mathcal{J}_k}\, \mathcal{U}_k^\dagger\right) \mathcal{U}_\text{final}\]where each \(\mathcal{U}_k\) is an
OrbitalRotation, each \(\mathcal{J}_k\) is a diagonal Coulomb operator\[\mathcal{J} = \frac12 \sum_{ij,\sigma\tau} \mathbf{J}^{\sigma\tau}_{ij}\, n_{i\sigma}\, n_{j\tau},\]and \(\mathcal{U}_\text{final}\) is an optional final orbital rotation. The number of terms \(L\) is the number of ansatz repetitions.
This gate supports three spin variants (see
UCJ.Variant), selected explicitly by thevariantargument and validated against the shapes of the supplied tensors (mirroring ffsim’sUCJOpSpinBalanced,UCJOpSpinUnbalancedandUCJOpSpinless). The number of spatial orbitals is not a constructor argument – it is inferred from those same tensor shapes (seenorb):spin-balanced –
diag_coulomb_matshas shape(L, 2, norb, norb)(the[alpha-alpha, alpha-beta]matrices, with beta-beta reusing alpha-alpha and beta-alpha reusing alpha-beta) andorbital_rotationshas shape(L, norb, norb)(one rotation applied to both spin sectors). Acts on2 * norbblock-spin modes.spin-unbalanced –
diag_coulomb_matshas shape(L, 3, norb, norb)(the[alpha-alpha, alpha-beta, beta-beta]matrices) andorbital_rotationshas shape(L, 2, norb, norb)(independent[alpha, beta]rotations). Acts on2 * norbblock-spin modes.spinless –
diag_coulomb_matsandorbital_rotationsboth have shape(L, norb, norb). Acts onnorbspinless modes. The equivalent two-register operator with a shared same-spin diagonal Coulomb matrix and no cross-spin interaction is expressible via the"balanced"variant with its alpha-beta block set to zero.
Note
This gate builds the ansatz from exact tensors. To use ffsim’s optimized (“compressed”) double factorization, construct an
ffsimUCJ operator withoptimize=Trueand pass itsdiag_coulomb_mats/orbital_rotations/final_orbital_rotationinto this constructor directly.Caution
This is an early development prototype. Beware of changes to its interface without warning during the pre-release development of this package.
Initializing an instance of this gate can be done with the arguments listed below.
The number of spatial orbitals is inferred from the supplied tensor shapes (see
norb).- Parameters:
variant (UCJ.Variant | str) – the spin variant, a
UCJ.Variant(or its string value"balanced","unbalanced", or"spinless"). Determines the number of modes this gate acts on (see the class docstring) and the expected tensor shapes.diag_coulomb_mats (np.ndarray) – the diagonal Coulomb matrices, of shape
(L, 2, norb, norb)(spin-balanced),(L, 3, norb, norb)(spin-unbalanced), or(L, norb, norb)(spinless), whereLis the number of ansatz repetitions.orbital_rotations (np.ndarray) – the orbital rotations, of shape
(L, norb, norb)(spin-balanced or spinless) or(L, 2, norb, norb)(spin-unbalanced).final_orbital_rotation (np.ndarray | None) – an optional final orbital rotation, of shape
(norb, norb)(spin-balanced or spinless) or(2, norb, norb)(spin-unbalanced).
- Raises:
ValueError – if
variantis not recognized, or if the tensor shapes are inconsistent with each other or withvariant.
Attributes
- diag_coulomb_mats¶
The diagonal Coulomb matrices defining each ansatz repetition.
- orbital_rotations¶
The orbital rotations defining each ansatz repetition.
- final_orbital_rotation¶
The optional final orbital rotation.
- norb¶
The number of spatial orbitals, inferred from the tensor shapes.
Methods
- classmethod from_parameters(params, norb, variant, n_reps, *, interaction_pairs=None, with_final_orbital_rotation=False)¶
Constructs a UCJ ansatz from a real-valued parameter vector.
- Parameters:
params (ndarray) – the real-valued parameter vector.
norb (int) – the number of spatial orbitals.
variant (Variant | str) – the spin variant, a
UCJ.Variant(or its string value"balanced","unbalanced", or"spinless").n_reps (int) – the number of ansatz repetitions.
interaction_pairs (list[tuple[int, int]] | tuple[list[tuple[int, int]] | None, ...] | None) – the allowed diagonal Coulomb interactions (see
from_t_amplitudes()for the exact per-variant shape convention).None(the default) imposes no restriction, so every block uses its full parameter count.with_final_orbital_rotation (bool) – whether
paramsincludes a trailing final orbital rotation.
- Returns:
The constructed
UCJgate.- Raises:
ValueError – if
variantis not recognized, or iflen(params)does not matchnum_parameters()for the given settings.- Return type:
- classmethod from_t_amplitudes(nelec, t2, *, t1=None, variant='balanced', n_reps=None, interaction_pairs=None, tol=1e-08)¶
Constructs a UCJ ansatz from coupled-cluster \(t_2\) (and optional \(t_1\)) amplitudes.
The ansatz layers are obtained from an exact double factorization of the \(t_2\) amplitudes (via
double_factorized_t2()/double_factorized_t2_alpha_beta()) and, when \(t_1\) is supplied, a final orbital rotation fromOrbitalRotation.from_t1_amplitudes().Note
Only the exact factorization is supported here. To use ffsim’s optimized (“compressed”) double factorization, build an
ffsimUCJ operator withoptimize=Trueand pass its tensors intoUCJdirectly.- Parameters:
nelec (int | tuple[int, int]) – either a single integer for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
t2 (ndarray | tuple[ndarray, ndarray, ndarray]) – the \(t_2\) amplitudes. For the
"balanced"and"spinless"variants, a single array of shape(nocc, nocc, nvrt, nvrt). For the"unbalanced"variant, a tuple(t2aa, t2ab, t2bb).t1 (ndarray | tuple[ndarray, ndarray] | None) – the optional \(t_1\) amplitudes producing the final orbital rotation. For
"unbalanced", a pair(t1a, t1b); otherwise a single array of shape(nocc, nvrt).variant (Variant | str) – the spin variant to build, a
UCJ.Variant(or its string value"balanced","unbalanced", or"spinless").n_reps (int | tuple[int, int] | None) – the number of ansatz repetitions. If
None, uses all terms of the double factorization; if larger, the ansatz is padded with identity rotations and zero diagonal Coulomb matrices. For the"unbalanced"variant a pair(n_reps_ab, n_reps_same_spin)independently sets the number of alpha-beta and same-spin terms; a tuple is only valid for that variant.interaction_pairs (list[tuple[int, int]] | tuple[list[tuple[int, int]] | None, ...] | None) – the allowed diagonal Coulomb interactions (the “local” in LUCJ). For
"spinless"a single list of upper-triangular(i, j)pairs; for"balanced"a pair(pairs_aa, pairs_ab); for"unbalanced"a triple(pairs_aa, pairs_ab, pairs_bb). A list of pairs restricts that block to exactly those entries; the same-spin (aa/bb) masks are symmetrized while the alpha-beta (ab) mask is not. UseNone– not an empty list[]– to impose no restriction: aNoneelement (or the whole argument beingNone) leaves the block untouched, whereas an empty list allows no interactions and so zeros the entire block.tol (float) – the double-factorization truncation tolerance.
- Returns:
The constructed
UCJgate.- Raises:
ValueError – if
variantis not recognized, or if a tuplen_repsis passed for a variant other thanUCJ.Variant.UNBALANCED.- Return type:
- classmethod num_parameters(norb, variant, n_reps, *, interaction_pairs=None, with_final_orbital_rotation=False)¶
Returns the number of parameters of a UCJ ansatz with the given settings.
- Parameters:
norb (int) – the number of spatial orbitals.
variant (Variant | str) – the spin variant, a
UCJ.Variant(or its string value"balanced","unbalanced", or"spinless").n_reps (int) – the number of ansatz repetitions.
interaction_pairs (list[tuple[int, int]] | tuple[list[tuple[int, int]] | None, ...] | None) – the allowed diagonal Coulomb interactions (see
from_t_amplitudes()for the exact per-variant shape convention).None(the default) imposes no restriction, so every block uses its full parameter count.with_final_orbital_rotation (bool) – whether the ansatz includes a final orbital rotation.
- Returns:
The number of parameters.
- Raises:
ValueError – if
variantis not recognized.- Return type:
- to_parameters(*, interaction_pairs=None)¶
Converts this UCJ ansatz to a real-valued parameter vector.
Note
If
interaction_pairsrestricts a block, the returned parameter vector incorporates only the diagonal Coulomb matrix entries corresponding to the allowed interactions, so the original operator is not recoverable from the parameter vector alone.Note
The returned vector is the principal-branch representative of this ansatz’s orbital rotations: each rotation is parameterized by
logm(U), which is unique only up to \(2\pi i\) shifts of its eigenvalue phases. Consequentlyfrom_parameters()applied to the returned vector reproduces this operator exactly, but the reverse composition does not generally return its input –to_parameters(from_parameters(p))equalsponly whenp’s generators already lie in the principal branch (all eigenvalue phases within \((-\pi, \pi]\)). Both a wrappedpand the returned vector describe the same unitary, so the operator is unaffected. Amplitudes fromfrom_t_amplitudes()are well inside the principal branch; large hand-built parameter vectors need not be.- Parameters:
interaction_pairs (list[tuple[int, int]] | tuple[list[tuple[int, int]] | None, ...] | None) – the allowed diagonal Coulomb interactions (see
from_t_amplitudes()for the exact per-variant shape convention).None(the default) imposes no restriction, so every block’s full contents are included.- Returns:
The real-valued parameter vector.
- Return type:
Protocol Methods
- _apply_unitary_placed_(vec, norb, nelec, copy, freg_indices)¶
Applies the ansatz after placing its modes onto the vector’s global modes.
This builds the gate’s definition (the per-repetition orbital rotations and diagonal Coulomb evolutions) and applies it to
vec, with the definition circuit placed onto the global modesfreg_indices(each of its instructions is relabeled onto the corresponding absolute modes). See_define()for the exact gate sequence.- Parameters:
vec (ndarray) – the state vector to act on.
norb (int) – the number of spatial orbitals of the global state vector.
nelec (int | tuple[int, int]) – either a single integer for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions.
copy (bool) – whether to copy the vector before operating on it.
freg_indices (list[int]) – the absolute (global) mode indices that this gate’s local modes map onto.
- Returns:
The transformed vector.
- Return type: