## `eigenkit.chemistry.vqe`

VQE — the Variational Quantum Eigensolver, on the core spine.

Given a qubit Hamiltonian (an `Observable` plus its constant offset), VQE minimizes `<H>` over a parametrized ansatz to estimate the ground-state energy. It is a thin layer over `minimize_expectation`: build an ansatz, wrap it in a numpy `Circuit` whose observable is the Hamiltonian, optimize. Pure core (numpy/scipy), torch-free, backend-agnostic.

The default ansatz is a hardware-efficient one (RY/RZ rotations + a linear CNOT entangler) starting from |0...0>, so it needs no Hartree-Fock preparation. For a chemistry-specific ansatz, pass `uccsd_ansatz(...)` as `ansatz`; it starts from the Hartree-Fock reference itself.

## `eigenkit.chemistry.vqe.VQE`

Bases: `BaseQuantumSolver`

Variational Quantum Eigensolver (VQE).

Parameters:

| Name           | Type           | Description                                                                                                                                      | Default                                                                                                    |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `layers`       | `int`          | The depth of the default hardware-efficient ansatz. The default is 2.                                                                            | `2`                                                                                                        |
| `provider`     | `ProviderSpec` | The backend to use. The default is "numpy", the built-in reference simulator.                                                                    | `'numpy'`                                                                                                  |
| `optimizer`    | `Optimizer`    | The optimiser: the name of a scipy.optimize.minimize method, "spsa", or a custom callable (see minimize_expectation). The default is "L-BFGS-B". | `'L-BFGS-B'`                                                                                               |
| `restarts`     | `int`          | The number of runs from random starting points. The lowest energy is kept, because variational landscapes have local minima. The default is 1.   | `1`                                                                                                        |
| `random_state` | \`int          | None\`                                                                                                                                           | The base seed. Restart r uses random_state + r, and None leaves every restart unseeded. The default is 42. |

### `solve(hamiltonian, n_qubits, *, offset=0.0, ansatz=None)`

Minimise the expectation value of the Hamiltonian over the ansatz.

It runs `restarts` independent optimisations from different random starting points and keeps the lowest energy, because a variational landscape has local minima.

Parameters:

| Name          | Type          | Description                                                                                                                                                                                                                                                    | Default                                                                                                     |
| ------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `hamiltonian` | `Observable`  | The Hamiltonian to minimise, as a qubit Observable, usually the one returned by jordan_wigner.                                                                                                                                                                 | *required*                                                                                                  |
| `n_qubits`    | `int`         | The number of qubits of the circuit. It must match the Hamiltonian.                                                                                                                                                                                            | *required*                                                                                                  |
| `offset`      | `float`       | The constant added to the minimised value. This is where the identity term returned by the mapping goes, which for a molecule includes the nuclear repulsion, in Hartree. If it is left out, the energy is wrong by exactly that constant. The default is 0.0. | `0.0`                                                                                                       |
| `ansatz`      | \`CircuitSpec | None\`                                                                                                                                                                                                                                                         | The circuit to optimise. The default, None, uses the built-in hardware-efficient ansatz with layers layers. |

Returns:

| Type        | Description                                                                           |
| ----------- | ------------------------------------------------------------------------------------- |
| `VQEResult` | A VQEResult with the best energy, its parameters, and whether that restart converged. |

## `eigenkit.chemistry.vqe.VQEResult`

Bases: `ValueEquality`

Outcome of a run of the Variational Quantum Eigensolver (VQE).

The result is read-only. Assigning to a field raises `FrozenInstanceError`, and writing into an array field raises `ValueError`. This prevents a mistyped `=` (instead of `==`) or an in-place edit from leaving a result whose scalar fields describe a different run from the array it holds. To get a writable copy of the array, use `np.array(result.field)`.

Results compare by value, including their arrays. They are not hashable, because a result is a collection of numbers and not a key, and a correct hash of a float array is expensive to compute.

Attributes:

| Name                 | Type      | Description                                                                             |
| -------------------- | --------- | --------------------------------------------------------------------------------------- |
| `energy`             | `float`   | The lowest energy found, with the offset added back. For a molecule, it is in Hartree.  |
| `optimal_parameters` | `ndarray` | The ansatz weights that produced this energy.                                           |
| `n_iterations`       | `int`     | The number of optimiser iterations in the best restart. It is not summed over restarts. |
| `success`            | `bool`    | Whether the optimiser of that restart reported convergence.                             |

### `__post_init__()`

Make the array field read-only.

Freezing the dataclass prevents a field from being reassigned, but it does not prevent writing into the array that the field holds, and a result that has been written into still reports the scalar values of the original run. The result therefore keeps its own copy, so the array it was built from can still be changed by the caller. To get a writable copy, use `np.array(result.optimal_parameters)`.

## `eigenkit.chemistry.vqe.hardware_efficient_ansatz(n_qubits, layers)`

A standard hardware-efficient ansatz.

It starts with a layer of `RY` rotations, then repeats `layers` times a linear chain of `CNOT` gates followed by an `RY` and an `RZ` rotation on each qubit. It has `n_qubits + 2 * layers * n_qubits` trainable weights.

Parameters:

| Name       | Type  | Description                | Default    |
| ---------- | ----- | -------------------------- | ---------- |
| `n_qubits` | `int` | The number of qubits.      | *required* |
| `layers`   | `int` | The number of repetitions. | *required* |

Returns:

| Type          | Description                   |
| ------------- | ----------------------------- |
| `CircuitSpec` | The ansatz, as a CircuitSpec. |
