Experiment
Experiments behave the same way as Processors and RemoteProcessors, except that they don’t know how or where to simulate them (they don’t have backend or platform); they simply describe the elements of an optical table and the post-processing rules.
>>> import perceval as pcvl
>>> e = pcvl.Experiment(2, noise=pcvl.NoiseModel(0.8), name="my experiment").add(0, pcvl.BS())
>>> e.add_herald(0, 1)
>>> p = pcvl.Processor("SLOS", e)
>>> rp = pcvl.RemoteProcessor("sim:slos").add(e)
Experiments have two main purposes that Processor
and RemoteProcessor
can’t fulfill:
They can be used to create several Processors describing the same experiment with different backends.
They can be serialized using perceval serialization, so they can be stored and retrieved easily.
>>> from perceval.serialization import serialize, deserialize
>>> e_str = serialize(e) # This is a regular string
>>> e_copy = deserialize(e_str)
- class perceval.components.experiment.Experiment(m_circuit=None, noise=None, name='Experiment')
This class represents an optical table containing:
A circuit and/or components that represent the operations that will operate on photons. Can contain non-unitary components
The input state for the experiment.
Detectors to detect photons.
Ports to define groups of modes
Heralds
A post-selection method
A NoiseModel
- Parameters:
m_circuit (int | ACircuit) – Number of spatial modes (int), first part of the circuit (Circuit) or None. If a circuit is passed, its size is used as the experiment size.
noise (NoiseModel) – A NoiseModel
name (str) – The experiment name
- add(mode_mapping, component, keep_port=True)
Add a component to the experiment (unitary or non-unitary).
- Parameters:
mode_mapping –
Describe how the new component is connected to the existing experiment. Can be:
an int: composition uses consecutive modes starting from mode_mapping
a list or a dict: describes the full mapping of length the input mode count of component
component –
The component to append to the experiment. Can be:
A unitary circuit
A non-unitary component
A processor
An experiment
A detector
keep_port (
bool
) – if True, saves self’s output ports on modes impacted by the new component, otherwise removes them.
Adding a component on non-ordered, non-consecutive modes computes the right permutation (PERM component) which fits into the existing experiment and the new component.
Example:
>>> e = Experiment(6) >>> e.add(0, BS()) # Modes (0, 1) connected to (0, 1) of the added beam splitter >>> e.add([2,5], BS()) # Modes (2, 5) of the experiment's output connected to (0, 1) of the added beam splitter >>> e.add({2:0, 5:1}, BS()) # Same as above
If the added component is a processor or an experiment with modes having heralds only on one side, no permutation will be added at the end, and the “in-between” modes will be pushed to the bottom.
- add_herald(mode, expected, name=None, location=PortLocation.IN_OUT)
Add a heralded mode
- Parameters:
mode (
int
) – Mode index of the heraldexpected (
int
) – number of expected photon as input AND output on the given mode (must be 0 or 1)name (
Optional
[str
]) – Herald port name. If none is passed, the name is auto-generatedlocation (
PortLocation
) – Port location of the herald (input, output or both)
- are_modes_free(mode_range, location=PortLocation.OUTPUT)
- Return type:
bool
- Returns:
True if all modes in mode_range are free of ports, for a given location (input, output or both)
- check_input(input_state)
Check if a basic state input matches with the current experiment configuration
- property circuit_size: int
- Returns:
Total size of the enclosed circuit (i.e. self.m + ancillary mode count)
- copy(subs=None)
Performs a deep copy of the current experiment.
- Return type:
- flatten(max_depth=None)
List all the components in the experiment where recursive circuits have been flattened.
- Parameters:
max_depth – The maximum depth of recursion. The remaining sub-circuits at this depth are listed as a component.
- Return type:
list
[tuple
]
- property has_feedforward: bool
- Returns:
True if the circuit contains at least one feed-forward layer, False otherwise.
- property has_td: bool
- Returns:
True if the circuit contains at least one time delay, False otherwise.
- property in_port_names
- Returns:
A list of the input port names. Names are repeated for ports connected to more than one mode
- property is_unitary: bool
- Returns:
True if the circuit is composed of only unitary components, False otherwise.
- property m: int
- Returns:
Number of modes of interest (MOI) at the output of the experiment
- property m_in
- Returns:
Number of modes of interest (MOI) at the input the experiment
- min_detected_photons_filter(n)
Sets-up a state post-selection on the number of detected photons. With thresholded detectors, this will actually filter on “click” count.
- Parameters:
n (
int
) – Minimum expected photons
This post-selection has an impact on the output physical performance
- property out_port_names
- Returns:
A list of the output port names. Names are repeated for ports connected to more than one mode
- set_circuit(circuit)
Removes all components and replace them by the given circuit.
- Parameters:
circuit (
ACircuit
) – The circuit to start the experiment with- Returns:
Self to allow direct chain this with .add()
- set_postselection(postselect)
Set a logical post-selection function. Along with the heralded modes, this function has an impact on the logical performance of the processor holding this experiment
- Parameters:
postselect (
PostSelect
) – Sets a post-selection function. Its signature must be func(s: BasicState) -> bool. If None is passed as parameter, removes the previously defined post-selection function.