UCJ

class UCJ(norb, nelec, diag_coulomb_mats, orbital_rotations, *, final_orbital_rotation=None, reference_occupation=None)

Bases: FermionicGate

Implements 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}\]

applied to a reference state (by default the Hartree-Fock determinant), 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 by the shapes of the supplied tensors and by nelec (mirroring ffsim’s UCJOpSpinBalanced, UCJOpSpinUnbalanced and UCJOpSpinless):

  • spin-balanceddiag_coulomb_mats has shape (L, 2, norb, norb) (the [alpha-alpha, alpha-beta] matrices, with beta-beta reusing alpha-alpha and beta-alpha reusing alpha-beta) and orbital_rotations has shape (L, norb, norb) (one rotation applied to both spin sectors).

  • spin-unbalanceddiag_coulomb_mats has shape (L, 3, norb, norb) (the [alpha-alpha, alpha-beta, beta-beta] matrices) and orbital_rotations has shape (L, 2, norb, norb) (independent [alpha, beta] rotations).

  • spinlessdiag_coulomb_mats and orbital_rotations both have shape (L, norb, norb). When nelec is an integer the gate acts on norb spinless modes; when nelec is a pair it acts on 2 * norb block-spin modes with the single diagonal Coulomb matrix used for both same-spin sectors and no cross-spin interaction.

Note

This gate builds the ansatz from exact tensors. To use ffsim’s optimized (“compressed”) double factorization, construct an ffsim UCJ operator with optimize=True and pass its diag_coulomb_mats / orbital_rotations / final_orbital_rotation into 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.

Parameters:
  • norb (int) – the number of spatial orbitals.

  • 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. Together with the tensor shapes this selects the spin variant (see the class docstring).

  • 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), where L is 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).

  • reference_occupation (Sequence[bool] | None) – the occupation (one boolean per mode) of the reference determinant the ansatz is applied to. Defaults to the Hartree-Fock determinant implied by nelec (the first n_alpha alpha modes and first n_beta beta modes occupied).

Raises:

ValueError – if the tensor shapes are inconsistent with each other, with norb, or with nelec.

Attributes

norb

The number of spatial orbitals.

nelec

The number of electrons (spinless) or the (n_alpha, n_beta) pair (spinful).

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.

reference_occupation

The occupation of the reference determinant the ansatz is applied to.

Methods

classmethod from_t_amplitudes(nelec, t2, *, t1=None, variant='balanced', n_reps=None, interaction_pairs=None, tol=1e-08, reference_occupation=None)

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 from OrbitalRotation.from_t1_amplitudes().

Note

Only the exact factorization is supported here. To use ffsim’s optimized (“compressed”) double factorization, build an ffsim UCJ operator with optimize=True and pass its tensors into UCJ directly.

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. Use None – not an empty list [] – to impose no restriction: a None element (or the whole argument being None) leaves the block untouched, whereas an empty list allows no interactions and so zeros the entire block.

  • tol (float) – the double-factorization truncation tolerance.

  • reference_occupation (Sequence[bool] | None) – forwarded to UCJ; defaults to the Hartree-Fock determinant.

Returns:

The constructed UCJ gate.

Raises:

ValueError – if variant is not recognized, or if a tuple n_reps is passed for a variant other than UCJ.Variant.UNBALANCED.

Return type:

UCJ