---
title: Evolution (latest version)
description: API reference for qiskit_fermions.circuit.library.Evolution in the latest version of qiskit-fermions
source: https://quantum.cloud.ibm.com/docs/en/api/qiskit-fermions/circuit-library-evolution
---

# Evolution

*class* `Evolution(num_modes, operator, time=1.0)`

Bases: [`FermionicGate`](/docs/api/qiskit-fermions/circuit-fermionic-gate "qiskit_fermions.circuit.fermionic_gate.FermionicGate")

Implements the time evolution of an operator.

Given a fermionic `operator` $H$ and an evolution `time` $t$, this gate implements the unitary

$$
U = e^{-i t H}.
$$

For $U$ to be unitary, $H$ must be Hermitian. This is the caller’s responsibility and is not verified.

> **Note**
>
> How this evolution is decomposed into a circuit is not fixed by this gate alone. The default `_define()` implementation splits the evolution group-by-group when the `operator` has [`groups`](/docs/api/qiskit-fermions/operators-fermion-operator#groups "qiskit_fermions.operators.FermionOperator.groups") assigned, and term-by-term otherwise, yielding a first-order product formula (which is exact only when the individual factors mutually commute). The transpilation process may further alter this decomposition (for example, [`QDriftTrotterization`](/docs/api/qiskit-fermions/transpiler-passes-q-drift-trotterization "qiskit_fermions.transpiler.passes.QDriftTrotterization") replaces it with a randomized product formula).

Initializing an instance of this gate can be done with the arguments listed below.

**Parameters**

- **num\_modes** ([*int*](https://docs.python.org/3/library/functions.html#int)) – the number of fermionic modes on which this gate acts.
- **operator** ([*OperatorTrait*](/docs/api/qiskit-fermions/operators-operator-trait "qiskit_fermions.operators.OperatorTrait")) – the Hermitian operator $H$ under which to time evolve the acted-upon fermionic modes.
- **time** ([*float*](https://docs.python.org/3/library/functions.html#float)) – the evolution time $t$ entering the exponent of $e^{-i t H}$. A negative value evolves backwards in time.

## Attributes

### operator

The operator under which to time evolve the acted-upon fermionic modes.

**Protocol Methods**

### \_apply\_unitary\_placed\_

`_apply_unitary_placed_(vec, norb, nelec, copy, freg_indices)`

Applies `exp(-i * time * operator)` after relabeling the operator to global modes.

The operator is relabeled onto its global modes and turned into a `scipy` `LinearOperator` via [`linear_operator()`](/docs/api/qiskit-fermions/linalg-linear-operator "qiskit_fermions.linalg.linear_operator") (backed by a native FCI matrix-vector kernel), then applied to the vector via `scipy.sparse.linalg.expm_multiply`. This mirrors ffsim’s own `_apply_unitary_` implementations (e.g. for its UCCSD operators).

**Parameters**

- **vec** (*np.ndarray*) – the state vector to act on.
- **norb** ([*int*](https://docs.python.org/3/library/functions.html#int)) – the number of spatial orbitals of the *global* state vector.
- **nelec** ([*int*](https://docs.python.org/3/library/functions.html#int)  *|*[*tuple*](https://docs.python.org/3/library/stdtypes.html#tuple)*\[*[*int*](https://docs.python.org/3/library/functions.html#int)*,* [*int*](https://docs.python.org/3/library/functions.html#int)*]*) – either a single integer for a spinless system, or a pair of integers storing the numbers of spin alpha and spin beta fermions. An integer selects the spinless mode interpretation (the operator’s `norb` modes are alpha orbitals); a pair selects the spinful `(orb, spin)` interpretation of the operator’s `2 * norb` modes.
- **copy** ([*bool*](https://docs.python.org/3/library/functions.html#bool)) – whether to copy the vector before operating on it.
- **freg\_indices** ([*list*](https://docs.python.org/3/library/stdtypes.html#list)*\[*[*int*](https://docs.python.org/3/library/functions.html#int)*]*) – the absolute (global) mode indices that this gate’s local modes map onto. The operator is relabeled from its local modes to these global modes before being applied, mirroring the transpiler’s synthesis pass.

**Returns**

The transformed vector.

**Raises**

- [**NotImplementedError**](https://docs.python.org/3/library/exceptions.html#NotImplementedError) – if the gate’s `operator` is not a [`FermionOperator`](/docs/api/qiskit-fermions/operators-fermion-operator "qiskit_fermions.operators.FermionOperator"). The simulation path is currently backed by the native FCI kernel, which only `FermionOperator` exposes (via [`SupportsLinearOperator`](/docs/api/qiskit-fermions/protocols-supports-linear-operator "qiskit_fermions.protocols.SupportsLinearOperator")); evolving other operator types is not yet supported.
- [**ValueError**](https://docs.python.org/3/library/exceptions.html#ValueError) – if the operator does not conserve the `(norb, nelec)` sector. Evolving under `exp(-i * time * operator)` only yields a unitary when `operator` maps the sector to itself; a term that leaves the sector would be silently projected to zero by the native kernel, producing a non-unitary, physically meaningless result. Such an operator is therefore rejected rather than applied. For a pair `nelec` the alpha and beta electron counts must *each* be conserved (particle number and the z-component of spin), matching the fixed sector the kernel represents.

**Return type**

np.ndarray
