UCCSD(weights, wires, s_wires=None, d_wires=None, init_state=None)[source]

Implements the Unitary Coupled-Cluster Singles and Doubles (UCCSD) ansatz.

The UCCSD ansatz calls the SingleExcitationUnitary() and DoubleExcitationUnitary() templates to exponentiate the coupled-cluster excitation operator. UCCSD is a VQE ansatz commonly used to run quantum chemistry simulations.

The UCCSD unitary, within the first-order Trotter approximation, is given by:

\[\hat{U}(\vec{\theta}) = \prod_{p > r} \mathrm{exp} \Big\{\theta_{pr} (\hat{c}_p^\dagger \hat{c}_r-\mathrm{H.c.}) \Big\} \prod_{p > q > r > s} \mathrm{exp} \Big\{\theta_{pqrs} (\hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s-\mathrm{H.c.}) \Big\}\]

where \(\hat{c}\) and \(\hat{c}^\dagger\) are the fermionic annihilation and creation operators and the indices \(r, s\) and \(p, q\) run over the occupied and unoccupied molecular orbitals, respectively. Using the Jordan-Wigner transformation the UCCSD unitary defined above can be written in terms of Pauli matrices as follows (for more details see arXiv:1805.04340):

\[\begin{split}\hat{U}(\vec{\theta}) = && \prod_{p > r} \mathrm{exp} \Big\{ \frac{i\theta_{pr}}{2} \bigotimes_{a=r+1}^{p-1} \hat{Z}_a (\hat{Y}_r \hat{X}_p - \mathrm{H.c.}) \Big\} \\ && \times \prod_{p > q > r > s} \mathrm{exp} \Big\{ \frac{i\theta_{pqrs}}{8} \bigotimes_{b=s+1}^{r-1} \hat{Z}_b \bigotimes_{a=q+1}^{p-1} \hat{Z}_a (\hat{X}_s \hat{X}_r \hat{Y}_q \hat{X}_p + \hat{Y}_s \hat{X}_r \hat{Y}_q \hat{Y}_p + \hat{X}_s \hat{Y}_r \hat{Y}_q \hat{Y}_p + \hat{X}_s \hat{X}_r \hat{X}_q \hat{Y}_p - \{\mathrm{H.c.}\}) \Big\}.\end{split}\]
  • weights (array) – Length len(s_wires) + len(d_wires) vector containing the parameters \(\theta_{pr}\) and \(\theta_{pqrs}\) entering the Z rotation in SingleExcitationUnitary() and DoubleExcitationUnitary(). These parameters are the coupled-cluster amplitudes that need to be optimized for each single and double excitation generated with the excitations() function.

  • wires (Iterable or Wires) – Wires that the template acts on. Accepts an iterable of numbers or strings, or a Wires object.

  • s_wires (Sequence[Sequence]) – Sequence of lists containing the wires [r,...,p] resulting from the single excitation \(\vert r, p \rangle = \hat{c}_p^\dagger \hat{c}_r \vert \mathrm{HF} \rangle\), where \(\vert \mathrm{HF} \rangle\) denotes the Hartee-Fock reference state. The first (last) entry r (p) is considered the wire representing the occupied (unoccupied) orbital where the electron is annihilated (created).

  • d_wires (Sequence[Sequence[Sequence]]) – Sequence of lists, each containing two lists that specify the indices [s, ...,r] and [q,..., p] defining the double excitation \(\vert s, r, q, p \rangle = \hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s \vert \mathrm{HF} \rangle\). The entries s and r are wires representing two occupied orbitals where the two electrons are annihilated while the entries q and p correspond to the wires representing two unoccupied orbitals where the electrons are created. Wires in-between represent the occupied and unoccupied orbitals in the intervals [s, r] and [q, p], respectively.

  • init_state (array[int]) – Length len(wires) occupation-number vector representing the HF state. init_state is used to initialize the wires.


ValueError – if inputs do not have the correct format

Notice that:

  1. The number of wires has to be equal to the number of spin orbitals included in the active space.

  2. The single and double excitations can be generated be generated with the function excitations(). See example below.

  3. The vector of parameters weights is a one-dimensional array of size len(s_wires)+len(d_wires)

An example of how to use this template is shown below:

import pennylane as qml
from pennylane import qchem
from pennylane.templates import UCCSD

from functools import partial

# Build the electronic Hamiltonian
name = "h2"
geo_file = "h2.xyz"
h, qubits = qchem.molecular_hamiltonian(name, geo_file)

# Number of electrons
electrons = 2

# Define the HF state
ref_state = qchem.hf_state(electrons, qubits)

# Generate single and double excitations
singles, doubles = qchem.excitations(electrons, qubits)

# Map excitations to the wires the UCCSD circuit will act on
s_wires, d_wires = qchem.excitations_to_wires(singles, doubles)

# Define the device
dev = qml.device('default.qubit', wires=qubits)

# Define the UCCSD ansatz
ansatz = partial(UCCSD, init_state=ref_state, s_wires=s_wires, d_wires=d_wires)

# Define the cost function
cost_fn = qml.ExpvalCost(ansatz, h, dev)

# Compute the expectation value of 'h' for given set of parameters 'params'
params = np.random.normal(0, np.pi, len(singles) + len(doubles))