## `eigenkit.photonics.backends`

The photonic backends, which are executors that implement `Executor`.

`Executor` is the protocol defined in `photonics.executor`.

### `PercevalBackend`

The photonic executor that runs on a local Perceval simulator.

`compile(spec)` returns a `PercevalCompiled`.

Parameters:

| Name           | Type  | Description                                                                                                                                                                                                                                                                                                               | Default  |
| -------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `backend_name` | `str` | A Perceval backend that computes the full output distribution. "SLOS" (the default) and "Naive" are exact, while "MPS" and "NaiveApprox" approximate the distribution, and so the gradients too. Backends that only sample, such as "CliffordClifford2017", are rejected, because run returns probabilities, not samples. | `'SLOS'` |

Raises:

| Type         | Description                                 |
| ------------ | ------------------------------------------- |
| `ValueError` | If backend_name is unknown or only samples. |

#### `compile(spec)`

Wrap `spec` in a reusable handle. Perceval runs at each call of the handle.

Parameters:

| Name   | Type                  | Description             | Default    |
| ------ | --------------------- | ----------------------- | ---------- |
| `spec` | `PhotonicCircuitSpec` | The circuit to compile. | *required* |

Returns:

| Type               | Description                           |
| ------------------ | ------------------------------------- |
| `PercevalCompiled` | The PercevalCompiled handle for spec. |

### `PercevalCompiled`

A reusable handle to a compiled photonic circuit, cheap to call many times.

It is the linear-optics counterpart of `CompiledCircuit`. `PercevalBackend.compile` builds it.

Parameters:

| Name           | Type                  | Description                                                    | Default    |
| -------------- | --------------------- | -------------------------------------------------------------- | ---------- |
| `spec`         | `PhotonicCircuitSpec` | The circuit that this handle evaluates.                        | *required* |
| `backend_name` | `str`                 | The Perceval backend, as for PercevalBackend. Default: "SLOS". | `'SLOS'`   |

Raises:

| Type         | Description                                 |
| ------------ | ------------------------------------------- |
| `ValueError` | If backend_name is unknown or only samples. |

#### `expectation(weights, inputs, observable)`

Return the expectation value of a `PhotonicObservable`, as a single number.

The observable is diagonal in the Fock basis.

Parameters:

| Name         | Type                 | Description                          | Default    |
| ------------ | -------------------- | ------------------------------------ | ---------- |
| `weights`    | `ndarray`            | The 1-D weight vector.               | *required* |
| `inputs`     | `ndarray`            | The 1-D input vector.                | *required* |
| `observable` | `PhotonicObservable` | A PhotonNumber or a FockProbability. | *required* |

Raises:

| Type         | Description                                              |
| ------------ | -------------------------------------------------------- |
| `ValueError` | If observable can never match the output of the circuit. |

#### `jacobian(weights, inputs, observable, *, method='parameter_shift', need_weight_grad=True, need_input_grad=True)`

Return `(d<O>/d weights, d<O>/d inputs)` for an observable.

The observable is diagonal in the Fock basis. Only one sample is accepted (1-D weights and inputs).

Parameters:

| Name               | Type                 | Description                                                                                                                                                                               | Default             |
| ------------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `weights`          | `ndarray`            | The 1-D weight vector.                                                                                                                                                                    | *required*          |
| `inputs`           | `ndarray`            | The 1-D input vector.                                                                                                                                                                     | *required*          |
| `observable`       | `PhotonicObservable` | A PhotonNumber or a FockProbability.                                                                                                                                                      | *required*          |
| `method`           | `str`                | "parameter_shift" for the exact photonic parameter-shift rule (in gradients.py), or "finite_difference" for central finite differences, the reference method. Default: "parameter_shift". | `'parameter_shift'` |
| `need_weight_grad` | `bool`               | If True, compute the gradient with respect to the weights. If False, it is skipped, and None is returned in its place.                                                                    | `True`              |
| `need_input_grad`  | `bool`               | If True, compute the gradient with respect to the inputs. If False, it is skipped, and None is returned in its place.                                                                     | `True`              |

Raises:

| Type         | Description                               |
| ------------ | ----------------------------------------- |
| `ValueError` | If method is neither of these two values. |

#### `run(weights, inputs)`

Return the output distribution of photon numbers.

The distribution is a dictionary `{photon_counts_tuple: probability}`. Fock states with probability zero may be left out, because Perceval's `prob_distribution` is sparse.

Parameters:

| Name      | Type      | Description                                      | Default    |
| --------- | --------- | ------------------------------------------------ | ---------- |
| `weights` | `ndarray` | The 1-D weight vector, of length spec.n_weights. | *required* |
| `inputs`  | `ndarray` | The 1-D input vector, of length spec.n_inputs.   | *required* |

Raises:

| Type         | Description                               |
| ------------ | ----------------------------------------- |
| `ValueError` | If weights or inputs has the wrong shape. |
