UCC¶
- class UCC(variant, t1, t2, *, antisymmetric=False, atol=1e-08)¶
Bases:
FermionicGateImplements the unitary coupled cluster (UCC) ansatz.
A unitary coupled cluster operator has the form
\[e^{T - T^\dagger}\]where \(T = T_1 + T_2\) is the cluster operator built from the single and double fermionic excitations, parameterized by the \(t_1\) and \(t_2\) amplitudes. Since \(T - T^\dagger\) is anti-Hermitian, its exponential is unitary.
This gate supports three spin variants (see
UCC.Variant), selected explicitly by thevariantargument and validated against the shapes of the supplied amplitudes (mirroring ffsim’sUCCSDOpRestrictedRealandUCCSDOpUnrestrictedReal):restricted – a single spin-summed amplitude pair. The cluster operator is
\[\begin{align} T_1 &= \sum_{ia} t_{ia}\left( a^\dagger_{a\alpha} a_{i\alpha} + a^\dagger_{a\beta} a_{i\beta}\right), \\ T_2 &= \sum_{ijab} t_{ijab}\left[ \frac12\left( a^\dagger_{a\alpha} a^\dagger_{b\alpha} a_{j\alpha} a_{i\alpha} + a^\dagger_{a\beta} a^\dagger_{b\beta} a_{j\beta} a_{i\beta}\right) + a^\dagger_{a\alpha} a^\dagger_{b\beta} a_{j\beta} a_{i\alpha}\right], \end{align}\]with
t1of shape(nocc, nvrt)andt2of shape(nocc, nocc, nvrt, nvrt). Acts on2 * norbblock-spin modes.unrestricted – independent per-spin amplitudes. The cluster operator is
\[\begin{align} T_1 &= \sum_{ia} t^{(\alpha)}_{ia} a^\dagger_{a\alpha} a_{i\alpha} + \sum_{IA} t^{(\beta)}_{IA} a^\dagger_{A\beta} a_{I\beta}, \\ T_2 &= \frac14 \sum_{ijab} t^{(\alpha\alpha)}_{ijab} a^\dagger_{a\alpha} a^\dagger_{b\alpha} a_{j\alpha} a_{i\alpha} + \frac14 \sum_{IJAB} t^{(\beta\beta)}_{IJAB} a^\dagger_{A\beta} a^\dagger_{B\beta} a_{J\beta} a_{I\beta} + \sum_{iJaB} t^{(\alpha\beta)}_{iJaB} a^\dagger_{a\alpha} a^\dagger_{B\beta} a_{J\beta} a_{i\alpha}, \end{align}\]with
t1a pair(t1a, t1b)andt2a triple(t2aa, t2ab, t2bb). Acts on2 * norbblock-spin modes. Note that the occupied/virtual split is resolved per spin sector, so the two sectors may have different numbers of occupied orbitals.spinless – a single register of
norbspinless modes,\[T_1 = \sum_{ia} t_{ia}\, a^\dagger_a a_i, \qquad T_2 = \frac14 \sum_{ijab} t_{ijab}\, a^\dagger_a a^\dagger_b a_j a_i,\]with the same amplitude shapes as the
"restricted"variant. Acts onnorbmodes.
In every variant the occupied orbitals are ordered before the virtual ones, so orbital \(i < n_\text{occ}\) is occupied and orbital \(n_\text{occ} + a\) is virtual.
Note
Unlike
UCJ, this ansatz carries no final orbital rotation: its \(t_1\) amplitudes already provide the single excitations, so a trailing rotation would be redundant freedom. Append anOrbitalRotationexplicitly if you want one.Note
By default only the symmetry the cluster operator actually enforces is imposed on the same-spin \(t_2\) blocks. The stricter antisymmetry of the standard coupled-cluster convention is available opt-in via the
antisymmetricflag (seeantisymmetric), which both validates supplied amplitudes and shrinks the parameter vector accordingly. It is not supported for the"restricted"variant, whose single \(t_2\) also carries the cross-spin amplitudes.Note
Because the individual excitation terms of \(T - T^\dagger\) do not commute, the circuit
definition()this gate produces is a first-order product formula (Trotter) approximation of the exponential, not an exact decomposition – the usual situation for UCC ansatz circuits. The state-vector simulation path (_apply_unitary_placed_()), by contrast, applies the exponential exactly viascipy’sexpm_multiply. Consequently the simulated gate and its synthesized circuit agree only up to the Trotter error; use a higher-order product formula during transpilation to tighten it.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:
variant (UCC.Variant | str) – the spin variant, a
UCC.Variant(or its string value"restricted","unrestricted", or"spinless"). Determines the number of modes this gate acts on (see the class docstring) and the expected amplitude shapes.t1 (np.ndarray | tuple[np.ndarray, np.ndarray]) – the \(t_1\) (singles) amplitudes. For the
"restricted"and"spinless"variants, a single array of shape(nocc, nvrt). For the"unrestricted"variant, a pair(t1a, t1b).t2 (np.ndarray | tuple[np.ndarray, np.ndarray, np.ndarray]) – the \(t_2\) (doubles) amplitudes. For the
"restricted"and"spinless"variants, a single array of shape(nocc, nocc, nvrt, nvrt). For the"unrestricted"variant, a triple(t2aa, t2ab, t2bb).antisymmetric (bool) – whether the same-spin \(t_2\) blocks obey the separate occupied and virtual antisymmetry (the standard coupled-cluster convention, see
antisymmetric). WhenTruethe supplied blocks are validated against it and the parameter vector is restricted to the corresponding subspace. Not supported for the"restricted"variant.atol (float) – the absolute tolerance for the
antisymmetricvalidation.
- Raises:
ValueError – if
variantis not recognized, if the amplitude shapes are inconsistent with each other or withvariant, ifantisymmetricis requested for the"restricted"variant, or ifantisymmetricis requested but a same-spin \(t_2\) block violates that antisymmetry.
Attributes
- antisymmetric¶
Whether the same-spin \(t_2\) blocks obey the separate occupied/virtual antisymmetry.
The cluster operator only ever sees the part of a same-spin \(t_2\) block that is symmetric under the simultaneous exchange \(t_2[i,j,a,b] = t_2[j,i,b,a]\), because the underlying excitation \(a^\dagger_a a^\dagger_b a_j a_i\) is invariant under relabeling the pairs \((i,a) \leftrightarrow (j,b)\). That weaker symmetry is therefore always imposed.
The standard coupled-cluster convention additionally makes the block antisymmetric in each index pair separately, \(t_2[i,j,a,b] = -t_2[j,i,a,b] = -t_2[i,j,b,a]\), which is a strict subspace of the above. Setting this flag opts into that convention: the supplied amplitudes are validated against it, and
num_parameters()/from_parameters()/to_parameters()switch to the smaller parameter basis that spans exactly this subspace.
- norb¶
The number of spatial orbitals (or spinless modes, for the spinless variant).
Methods
- cluster_operator()¶
Returns the anti-Hermitian cluster generator \(T - T^\dagger\).
The generator is expressed in the block-spin mode convention (mode
pis alpha orbitalp, modenorb + pis beta orbitalp) for the spinful variants, and directly on thenorbmodes for the spinless variant. Occupied orbitals are ordered before virtual ones.Being anti-Hermitian, this generator relates to the ansatz unitary by \(e^{T - T^\dagger} = e^{-i H}\) with the Hermitian \(H = i (T - T^\dagger)\). That \(H\) is what
Evolutionconsumes, since it requires a Hermitian operator to produce a unitary, and it is how_build_definition()expresses the ansatz.The returned operator carries
groupsthat pair every excitation with its Hermitian conjugate. That grouping is load-bearing:Evolutiondecomposes group-by-group, so each group becomes one factor \(e^{-i H_k}\) of the product formula, and multiplying by \(i\) leaves every group individually Hermitian – hence every factor a genuine unitary. Splitting term-by-term instead would not be (see the comment below).- Returns:
The cluster generator \(T - T^\dagger\) as a
FermionOperator.- Return type:
- classmethod from_parameters(params, norb, nocc, variant, *, antisymmetric=False)¶
Constructs a UCC ansatz from a real-valued parameter vector.
With
antisymmetric=False(the default) the parameter ordering matches ffsim’sUCCSDOpRestrictedReal/UCCSDOpUnrestrictedRealconvention, so a vector produced by ffsim’s ownto_parametersround-trips through this method.With
antisymmetric=Truethe same-spin \(t_2\) blocks are instead built from the smaller basis spanning the standard coupled-cluster antisymmetric subspace (seeantisymmetric), so the expected vector length differs and ffsim’s vectors no longer apply.- Parameters:
params (ndarray) – the real-valued parameter vector.
norb (int) – the number of spatial orbitals (or spinless modes, for the spinless variant).
nocc (int | tuple[int, int]) – the number of occupied orbitals. For the
"unrestricted"variant a pair(nocc_a, nocc_b); otherwise a single integer.variant (Variant | str) – the spin variant, a
UCC.Variant(or its string value"restricted","unrestricted", or"spinless").antisymmetric (bool) – whether to build the same-spin \(t_2\) blocks in the antisymmetric subspace (see
antisymmetric). The resulting amplitudes then satisfy that antisymmetry by construction. Not supported for the"restricted"variant.
- Returns:
The constructed
UCCgate.- Raises:
ValueError – if
variantis not recognized, ifantisymmetricis requested for the"restricted"variant, or iflen(params)does not matchnum_parameters()for the given settings.- Return type:
- classmethod from_t_amplitudes(t2, *, t1=None, variant='restricted', antisymmetric=False, atol=1e-08)¶
Constructs a UCC ansatz from coupled-cluster \(t_2\) (and optional \(t_1\)) amplitudes.
This is a convenience constructor mirroring
UCJ.from_t_amplitudes(). Unlike the (L)UCJ ansatz – which factorizes the amplitudes into diagonal Coulomb layers – the UCC ansatz uses the amplitudes directly as its parameters, so this simply defaults an omittedt1to zeros of the shape implied byt2, giving a doubles-only (UCCD) ansatz.- Parameters:
t2 (ndarray | tuple[ndarray, ndarray, ndarray]) – the \(t_2\) amplitudes. For the
"restricted"and"spinless"variants, a single array of shape(nocc, nocc, nvrt, nvrt). For the"unrestricted"variant, a triple(t2aa, t2ab, t2bb).t1 (ndarray | tuple[ndarray, ndarray] | None) – the optional \(t_1\) amplitudes. For
"unrestricted", a pair(t1a, t1b); otherwise a single array of shape(nocc, nvrt). Defaults to zeros.variant (Variant | str) – the spin variant to build, a
UCC.Variant(or its string value"restricted","unrestricted", or"spinless").antisymmetric (bool) – whether to assert the standard coupled-cluster antisymmetry of the same-spin \(t_2\) blocks (see
antisymmetric). Amplitudes from a genuine coupled-cluster calculation satisfy it, so this is a cheap way to confirm they survived whatever preprocessing produced them. Not supported for the"restricted"variant.atol (float) – the absolute tolerance for the
antisymmetricvalidation.
- Returns:
The constructed
UCCgate.- Raises:
ValueError – if
variantis not recognized, if the amplitude shapes are inconsistent with each other or withvariant, ifantisymmetricis requested for the"restricted"variant, or ifantisymmetricis requested but a same-spin \(t_2\) block violates that antisymmetry.- Return type:
- classmethod num_parameters(norb, nocc, variant, *, antisymmetric=False)¶
Returns the number of parameters of a UCC ansatz with the given settings.
- Parameters:
norb (int) – the number of spatial orbitals (or spinless modes, for the spinless variant).
nocc (int | tuple[int, int]) – the number of occupied orbitals. For the
"unrestricted"variant a pair(nocc_a, nocc_b)giving the per-spin occupations; otherwise a single integer.variant (Variant | str) – the spin variant, a
UCC.Variant(or its string value"restricted","unrestricted", or"spinless").antisymmetric (bool) – whether the same-spin \(t_2\) blocks are restricted to the standard coupled-cluster antisymmetric subspace (see
antisymmetric), which needs strictly fewer parameters. Not supported for the"restricted"variant.
- Returns:
The number of parameters.
- Raises:
ValueError – if
variantis not recognized, ifnoccis a pair for a variant other thanUCC.Variant.UNRESTRICTED(or an integer for that variant), or ifantisymmetricis requested for the"restricted"variant.- Return type:
- to_parameters()¶
Converts this UCC ansatz to a real-valued parameter vector.
The inverse of
from_parameters(), using the same ordering and the same basis this gate’santisymmetricflag selects – sofrom_parameters(gate.to_parameters(), ...)round-trips as long as the flag is passed consistently.Note
Only the independent amplitude entries implied by the variant’s symmetries (and by
antisymmetric) are written out; seenum_parameters(). Amplitudes violating those symmetries – or carrying a non-negligible imaginary part – are therefore not recoverable from the parameter vector.Note
The round-trip is two-sided and holds at any parameter scale: the amplitudes are this ansatz’s parameters directly, so both directions are a plain re-indexing.
- 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 cluster-operator evolution) and applies it to
vec, with the definition circuit placed onto the global modesfreg_indices. Because the definition’s singleEvolutioncarries the whole cluster generator, its own_apply_unitary_placed_exponentiates it exactly (viascipy’sexpm_multiply) – so this path incurs no Trotter error, unlike the synthesized circuit. 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: