UCC
class UCC(uccsd_op)
Bases: FermionicGate
Implements the unitary coupled-cluster singles and doubles (UCCSD) ansatz.
A unitary coupled-cluster operator has the form
with occupied and virtual orbitals, and the amplitudes and supplied by the operator this gate wraps.
The operator itself is built by ffsim, and this gate turns it into a FermionicCircuit. That division of labor is deliberate: ffsim owns the ansatz math (the amplitude conventions and the parameter-vector packing that a variational optimizer drives), while this gate expresses the result as fermionic modes so that the transpiler can lower it through any fermion-to-qubit encoding. ffsim ships no Qiskit gate for UCCSD at all, so this is the only route from one of its UCCSD operators to a circuit; see the ffsim relationship guide.
Accepts any of ffsim’s four UCCSD operators, whose type fixes the spin variant and the number of modes this gate acts on. All four act on 2 * norb block-spin modes (mode p is alpha orbital p, mode norb + p is beta orbital p), with the occupied orbitals ordered before the virtual ones:
UCCSDOpRestrictedRealandUCCSDOpRestrictedshare one spatial parametrization between both spin sectors:t1has shape(nocc, nvrt)andt2has shape(nocc, nocc, nvrt, nvrt).UCCSDOpUnrestrictedRealandUCCSDOpUnrestrictedparameterize the spin sectors independently:t1is a pair(t1a, t1b)andt2a triple(t2aa, t2ab, t2bb).
The cluster operator only ever sees the part of a same-spin block that is symmetric under the simultaneous exchange , because the underlying excitation is invariant under relabeling the pairs . Coupled-cluster amplitudes (from PySCF, or ffsim’s own uccsd_generator_restricted()) always carry that symmetry, so this gate and ffsim agree exactly on them. A hand-built t2 without it describes the same ansatz here as its symmetrized counterpart, whereas ffsim reads the raw tensor.
Unlike UCJ, this ansatz carries no final orbital rotation of its own: its amplitudes already provide the single excitations, so a trailing rotation would be redundant freedom. ffsim’s operators do expose a final_orbital_rotation; when one is set, this gate appends it as a closing OrbitalRotation.
Because the individual excitation terms of 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 via scipy’s expm_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.
ffsim does not support Windows (through its unconditional PySCF dependency), so this gate requires the ffsim extra (pip install "qiskit-fermions[ffsim]") and is unavailable there. Use WSL on Windows.
This is an early development prototype. Beware of changes to its interface without warning during the pre-release development of this package.
>>> import ffsim
>>> import numpy as np
>>> from qiskit_fermions.circuit.library import UCC
>>> uccsd_op = ffsim.UCCSDOpRestrictedReal(
... t1=np.zeros((1, 1)), t2=np.zeros((1, 1, 1, 1))
... )
>>> gate = UCC(uccsd_op)
>>> gate.norb, gate.num_modes
(2, 4)
Initializing an instance of this gate can be done with the argument listed below.
Parameters
uccsd_op (Any) – the ffsim UCCSD operator to build the circuit from, one of UCCSDOpRestrictedReal, UCCSDOpRestricted, UCCSDOpUnrestrictedReal or UCCSDOpUnrestricted. Its type determines the spin variant (see the class docstring).
Raises
- MissingOptionalLibraryError – if
ffsimis not installed. - TypeError – if
uccsd_opis not one of ffsim’s four UCCSD operator types.
Attributes
norb
The number of spatial orbitals.
uccsd_op
The ffsim UCCSD operator this gate builds its circuit from.
Methods
cluster_operator
cluster_operator()
Returns the anti-Hermitian cluster generator .
The generator is expressed in the block-spin mode convention (mode p is alpha orbital p, mode norb + p is beta orbital p). Occupied orbitals are ordered before virtual ones.
Being anti-Hermitian, this generator relates to the ansatz unitary by with the Hermitian . That is what Evolution consumes, since it requires a Hermitian operator to produce a unitary, and it is how _build_definition() expresses the ansatz.
The returned operator carries groups that pair every excitation with its Hermitian conjugate. That grouping is load-bearing: Evolution decomposes group-by-group, so each group becomes one factor of the product formula, and multiplying by 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 as a FermionOperator.
Return type
Protocol Methods
_apply_unitary_placed_
_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 modes freg_indices. Because the definition’s single Evolution carries the whole cluster generator, its own _apply_unitary_placed_ exponentiates it exactly (via scipy’s expm_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