reservoir
eigenkit.photonics.reservoir
Photonic reservoir computing, as a quantum extreme learning machine.
The reservoir is a fixed linear-optical interferometer, which is random and never trained. At each timestep, the input is encoded into its phases, the photons pass through it, and photon-number statistics are read out. This gives a nonlinear map to many features. Only a classical linear readout is trained, so the executor only has to evaluate the circuit, and no gradients go through the optics.
The parts that do not depend on the kind of hardware come from the qubit reservoir
package, eigenkit.reservoir. This module uses its Stateless policy, which gives
temporal context with a classical window of past inputs, and the readout can be
that package's LinearReadout, a ridge regression solved in closed form. The part
specific to photonics turns the input of each timestep into a vector of features
from a Fock distribution, with a photonic Executor.
Scope: no memory, or a classical window of inputs (Stateless). Carrying the
photonic state from one timestep to the next (a quantum memory, like the qubit
Carry policy) needs the executor to accept a Fock state as input, and is not
supported yet. Policies that carry state raise an error here.
fock_basis(n_modes, n_photons)
Return the sorted list of output Fock states.
The list holds every way to place n_photons photons into n_modes modes.
Passive linear optics conserves the number of photons, so these are exactly the
outputs that the circuit can reach. They are the fixed columns of the feature
vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_modes
|
int
|
The number of optical modes. |
required |
n_photons
|
int
|
The total number of photons. |
required |
fock_probability_features(dist, basis)
Return the probability of every state in basis, as a dense vector.
These are the detailed features of the reservoir.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
dict
|
A Fock distribution, as |
required |
basis
|
list[tuple[int, ...]]
|
The output states, in the order of the
features, for example from |
required |
photon_number_features(dist, n_modes)
Return the expected number of photons <n̂_m> in each mode m.
This readout is compact, and easy to measure with detectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dist
|
dict
|
A Fock distribution, as |
required |
n_modes
|
int
|
The number of optical modes. |
required |
random_reservoir_spec(n_modes, n_inputs, *, depth=2, input_state=None, input_scale=1.0, rng=None)
Build a fixed, random photonic reservoir and its frozen weights.
A mixing layer comes first, so that the photons are spread over the modes. Then
the n_inputs features are encoded as phases on the modes 0 to
n_inputs - 1 (each multiplied by input_scale), and depth more mixing
layers follow. A mixing layer is a beam splitter on every pair of neighbouring
modes, followed by a phase shifter on every mode. All their angles are random
weights, drawn uniformly from [0, 2π).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_modes
|
int
|
The number of optical modes. It must be at least |
required |
n_inputs
|
int
|
The number of features encoded at each step, with one phase
each. It must be at least |
required |
depth
|
int
|
The number of mixing layers after the encoding. It must be at
least |
2
|
input_state
|
tuple[int, ...] | None
|
The Fock state sent into the circuit.
The default is a single photon in mode |
None
|
input_scale
|
float
|
The factor applied to each input before it is used as
a phase. Default: |
1.0
|
rng
|
Generator | None
|
The source of the random weights of the reservoir. The default is a new, unseeded generator. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
spec |
PhotonicCircuitSpec
|
The circuit of the reservoir. |
weights |
ndarray
|
The frozen weights of the reservoir, which are never trained. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
run_photonic_reservoir(spec, weights, sequences, *, executor=None, policy=None, features='fock')
Run the fixed reservoir over input sequences, and return the features.
The reservoir spec, with its frozen weights, is evaluated at every timestep
of sequences, of shape (B, T, F). The result is the sequence of features, of
shape (B, T, n_features).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
PhotonicCircuitSpec
|
The reservoir, for example from
|
required |
weights
|
ndarray
|
The frozen weights of the reservoir. |
required |
sequences
|
ndarray
|
The input sequences, of shape |
required |
executor
|
Executor | None
|
The executor that runs each step. The default
is |
None
|
policy
|
Stateless | None
|
The policy whose |
None
|
features
|
str
|
|
'fock'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The features, of shape |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NotImplementedError
|
If |