# InitializeModes

### *class* InitializeModes(occupation)

Prepares (or, under simulation, certifies) a fermionic mode occupation.

Bases: [`FermionicGate`](qiskit_fermions.circuit.FermionicGate.html.md#qiskit_fermions.circuit.FermionicGate)

This gate declares an intended occupation of the modes it is placed on. Its behavior depends on
how the circuit is consumed:

- **Transpiled** (synthesized to qubit gates): it *produces* the state – the synthesis plugin
  emits the gates that set the named modes to their occupation, as one would expect of an
  initialization gate.
- **Simulated** (`_apply_unitary_()`): it acts as a *validator* rather than a producer. Given
  a state vector it checks that the vector’s amplitude is confined to the subspace its
  [`occupation`](#qiskit_fermions.circuit.library.InitializeModes.occupation) defines and returns the vector unchanged, certifying – without mutating –
  that the incoming state is the intended reference so the transforms that follow act on it.

In both modes the gate constrains only the orbitals the occupation names (and, per spin sector,
only along that sector’s axis), so several [`InitializeModes`](#qiskit_fermions.circuit.library.InitializeModes) gates can be placed **in
parallel** to seed disjoint fragments of a state independently – e.g. one gate per spin sector,
or one per orbital group. A spinful gate may cover a single sector (any fragment of it) or fully
specify both sectors, but a partial straddle of both is rejected (see
[`_apply_unitary_placed_()`](#qiskit_fermions.circuit.library.InitializeModes._apply_unitary_placed_)).

Use [`from_hartree_fock()`](#qiskit_fermions.circuit.library.InitializeModes.from_hartree_fock) to construct the occupation of a Hartree-Fock reference.

#### 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:**
  **occupation** (*Sequence* *[*[*bool*](https://docs.python.org/3/builtins/functions.html#bool) *]*) – a sequence of booleans indicating the occupation for each mode in the
  [`FermionicRegister`](qiskit_fermions.circuit.FermionicRegister.html.md#qiskit_fermions.circuit.FermionicRegister) being initialized by this gate.

### Attributes

#### occupation

The sequence of booleans indicating the occupation for each mode in the
[`FermionicRegister`](qiskit_fermions.circuit.FermionicRegister.html.md#qiskit_fermions.circuit.FermionicRegister) being initialized by this gate.

### Methods

#### *classmethod* from_hartree_fock(norb, nelec)

Builds the gate for the Hartree-Fock reference occupation of `(norb, nelec)`.

The Hartree-Fock determinant fills the lowest-indexed orbitals of each spin sector. Whether
the reference is spinless or spinful is inferred from `nelec` (an `int` selects the
spinless interpretation of the `norb` modes; a `(n_alpha, n_beta)` pair selects the
spinful block-spin interpretation of the `2 * norb` modes). Place the returned gate on the
matching register to certify a Hartree-Fock reference state.

* **Parameters:**
  * **norb** ([*int*](https://docs.python.org/3/builtins/functions.html#int)) – the number of spatial orbitals.
  * **nelec** ([*int*](https://docs.python.org/3/builtins/functions.html#int) *|* [*tuple*](https://docs.python.org/3/builtins/stdtypes.html#tuple) *[*[*int*](https://docs.python.org/3/builtins/functions.html#int) *,* [*int*](https://docs.python.org/3/builtins/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.
* **Returns:**
  An [`InitializeModes`](#qiskit_fermions.circuit.library.InitializeModes) gate whose occupation is the Hartree-Fock determinant.
* **Raises:**
  [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError) – if the electron count exceeds the `norb` orbitals available in a sector.
* **Return type:**
  [*Self*](https://docs.python.org/3/library/typing.html#typing.Self)

### Protocol Methods

#### \_apply_unitary_placed_(vec, norb, nelec, copy, freg_indices)

Asserts that `vec` is confined to this gate’s occupation subspace, returning it unchanged.

Unlike a transform gate, this gate does not modify the state: it *checks* that `vec`’s
amplitude lives entirely in the subspace its [`occupation`](#qiskit_fermions.circuit.library.InitializeModes.occupation) defines, and if so returns
`vec` untouched. The subspace is the set of determinants whose occupation agrees with this
gate on the orbitals it names, with every unnamed orbital left free – so a partial occupation
(a fragment of a sector) accepts a whole family of determinants and the check composes with
other parallel [`InitializeModes`](#qiskit_fermions.circuit.library.InitializeModes) gates.

The gate’s local [`occupation`](#qiskit_fermions.circuit.library.InitializeModes.occupation) (one flag per local mode) is placed onto the global
register via `freg_indices`: local mode `i` constrains global mode `freg_indices[i]`.
The global modes are then interpreted under the `(norb, nelec)` convention:

- **Spinless** (`nelec` is an `int`): the `norb` modes are orbitals directly; the check
  is over the `C(norb, nelec)`-dimensional space.
- **Spinful** (`nelec` is a pair): under the block-spin convention modes `0..norb` are
  alpha orbitals and modes `norb..2*norb` are beta orbitals. A gate touching a single
  sector constrains that sector’s axis of the `(dim_a, dim_b)` state (a set of full rows
  for an alpha gate, or full columns for a beta gate) and leaves the other axis free, so it
  composes with parallel gates on the other sector. A gate may also cover *both* sectors, but
  only when it pins a complete determinant (every orbital of both sectors named, none left
  free); a *partial* straddle – constraining some orbitals of both sectors while leaving
  others free – is rejected, since it is not a product of per-axis subspaces and cannot
  compose (use one gate per sector instead).

The check is on *confinement*, not equality: an incoming amplitude may carry any phase and
any magnitude within the subspace (a global phase or normalization is physically irrelevant),
so this validates the reference without pinning it to a specific determinant vector.

* **Parameters:**
  * **vec** ([*ndarray*](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy.ndarray)) – the state vector to validate. Its length must match the `(norb, nelec)` sector
    dimension.
  * **norb** ([*int*](https://docs.python.org/3/builtins/functions.html#int)) – the number of spatial orbitals of the *global* state vector.
  * **nelec** ([*int*](https://docs.python.org/3/builtins/functions.html#int) *|* [*tuple*](https://docs.python.org/3/builtins/stdtypes.html#tuple) *[*[*int*](https://docs.python.org/3/builtins/functions.html#int) *,* [*int*](https://docs.python.org/3/builtins/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 `norb` modes are orbitals); a pair selects the spinful
    `(orb, spin)` block-spin interpretation of the `2 * norb` modes.
  * **copy** ([*bool*](https://docs.python.org/3/builtins/functions.html#bool)) – accepted for protocol conformance but has no effect – this gate does not mutate the
    state, so `vec` is returned as-is regardless.
  * **freg_indices** ([*list*](https://docs.python.org/3/builtins/stdtypes.html#list) *[*[*int*](https://docs.python.org/3/builtins/functions.html#int) *]*) – the absolute (global) mode indices that this gate’s local modes map onto.
* **Returns:**
  The input `vec`, unchanged, once its confinement to the occupation subspace is verified.
* **Raises:**
  [**ValueError**](https://docs.python.org/3/builtins/exceptions.html#ValueError) – if an occupied mode falls outside the range implied by `norb`; if a spinful
      gate partially straddles both spin sectors (without pinning a full determinant); if
      `vec`’s length does not match the `(norb, nelec)` sector dimension; or if `vec`
      has amplitude outside the subspace the occupation defines.
* **Return type:**
  [*ndarray*](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html#numpy.ndarray)
