Skip to content

perceval_backend

eigenkit.photonics.backends.perceval_backend

The Perceval executor for photonic circuits (experimental).

It translates a PhotonicCircuitSpec into a Perceval Circuit, and computes the output distribution of photon numbers with an exact Perceval simulator, by default simulation of linear optical systems (SLOS). It is the linear-optics counterpart of a qubit Provider, but it does not implement the qubit Provider protocol: there is no CircuitSpec, no Pauli Observable and no array of expectation values. This is why photonics is a separate package.

perceval is imported only inside the methods, when they run, so importing this module (and therefore import eigenkit) never imports the Perceval software development kit (SDK). The data module photonics.ir never uses Perceval at all.

The work is split between compilation and evaluation, as in the qubit providers: compile() is called once, and run(weights, inputs) at every call. For now, the Perceval circuit is built again at every call, after the Parameter expressions are evaluated to numbers. Building it once with symbolic pcvl.P parameters, and setting their values at each call, is not done yet. (This is the saving that the qubit providers get from the split between compilation and evaluation.)

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.

build_perceval_circuit(spec, weights, inputs)

Translate a PhotonicCircuitSpec into a Perceval Circuit.

The Parameter angles are evaluated to numbers first. The local and the remote executors both use this function, so they build exactly the same circuit. (The live test of the remote executor compares sampled and exact results on the same circuit.)

Parameters:

Name Type Description Default
spec PhotonicCircuitSpec

The circuit to translate.

required
weights ndarray

The 1-D weight vector used to evaluate the angles.

required
inputs ndarray

The 1-D input vector used to evaluate the angles.

required

Returns:

Name Type Description
circuit Circuit

The circuit, on spec.n_modes modes.

Raises:

Type Description
ValueError

If weights or inputs is not 1-D with the length that the spec declares.

fock_tuple(state, n_modes)

Convert a Perceval BasicState, or any indexable object, to a tuple of photon counts.

Parameters:

Name Type Description Default
state BasicState | Sequence[int]

The number of photons in each mode, indexed by mode.

required
n_modes int

The number of modes to read.

required

Returns:

Type Description
tuple[int, ...]

The number of photons in each mode, as a tuple of integers.