Skip to content

executor

eigenkit.photonics.executor

The executor protocol for photonic circuits, the linear-optics counterpart of core.provider.

A photonic executor compiles a PhotonicCircuitSpec into a Compiled handle that can be reused. This is a different contract from the qubit core.provider.Provider: there is no CircuitSpec, no Pauli Observable and no array of expectation values. This is why photonics is a separate package, and not a qubit backend.

The executors themselves are in photonics/backends/ (for example, the Perceval backend, which uses Perceval's simulation of linear optical systems (SLOS)). This module does not depend on any framework (neither Perceval nor PyTorch). It defines only the contract, and a small registry of names whose executors are built on first use, like the one in core.provider.

Compiled

Bases: Protocol

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

Its contents are internal to the executor that built it.

expectation(weights, inputs, observable)

Evaluate one observable that is diagonal in the Fock basis, for one sample.

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

Returns:

Type Description
float

The expectation value of observable.

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

Compute the gradient of one observable with respect to 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

How to differentiate, for example "parameter_shift".

'parameter_shift'
need_weight_grad bool

If True, compute the gradient with respect to the weights. If False, the implementation may skip it and return None in its place. The PyTorch bridge takes this value from ctx.needs_input_grad.

True
need_input_grad bool

The same as need_weight_grad, for the gradient with respect to the inputs.

True

Returns:

Name Type Description
weight_jac ndarray | None

The derivatives d<O>/d weights, or None if they were not requested.

input_jac ndarray | None

The derivatives d<O>/d inputs, or None if they were not requested.

run(weights, inputs)

Evaluate the circuit for one sample.

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

Returns:

Type Description
dict

The output Fock distribution, as a dictionary {photon_counts_tuple: probability}.

Executor

Bases: Protocol

An object that compiles a PhotonicCircuitSpec into a Compiled handle.

The handle can be reused for many evaluations.

compile(spec)

Prepare spec so that it can be evaluated many times.

Parameters:

Name Type Description Default
spec PhotonicCircuitSpec

The circuit to compile.

required

Returns:

Type Description
Compiled

A Compiled handle for spec.

get(name)

Return the executor registered under name, building it on first use.

Parameters:

Name Type Description Default
name str

A name passed to register_lazy.

required

Returns:

Name Type Description
executor Executor

The executor. It is kept after the first call, and the same object is returned by later calls.

Raises:

Type Description
KeyError

If nothing is registered under name.

register_lazy(name, loader)

Register a function that builds an executor, without building it yet.

The first registration of a name is kept, and later ones are ignored.

Parameters:

Name Type Description Default
name str

The name that get looks up.

required
loader Callable[[], Executor]

A function with no arguments that builds the executor. It is called the first time the name is looked up.

required

registered_names()

Return the names of all registered executors, in sorted order.