This repository contains software to accompany the paper
Samo Novák and David D. Roberts and Alexander Makarovskiy and Raúl García-Patrón and William R. Clements. "Boundaries for quantum advantage with single photons and loop-based time-bin interferometers" (2024). arXiv:2411.16873 [quant-ph]
The repository contains:
- a reference implementation of the progressive simulation algorithm for loop-based Boson Sampling systems (see
loop_progressive_simulator/), - code and utilities used to compute the memory complexity of such simulation using the lattice path formalism introduced in the paper (see
shell_utilities/run_experiment_families.py, - a Jupyter notebook used to generate the figures in the paper (
notebooks/paper_plot_generation.ipynb).
The utilities to run experiments and compute their sampling complexities are found in shell_utilities/. To allow for easy generation of a large amount of different experiments, we use a two-layered architecture consisting of an experiment scheduler run_experiment_families.py acting as the recommended user interface, and the code to run an individual experiment complexity_experiment.py.
The scheduler run_experiment_families.py will run complexity_experiment.py several times to generate many instances of given experiments. The scheduler will use multiple CPUs (if available) to do this, parallelizing the work.
In the following, we call the set of instances of a given experiment (a specified number of modes, input state, loops, etc.) an experiment family.
The recommended way to use the utilities is to run shell_utilities/run_experiment_families.pysupplied with arguments defining families of experiments, possibly parametrized on the number of modes, photons, loop lengths, etc. The general syntax is:
python3 run_experiment_families.py -E "<experiment specification>" [-E "<...>"] ... -P <max_proc>Here, the argument -E defines experiment families, and its contents are a string (enclosed in quotation marks) consisting of experiment arguments defined below. A call like above may contain one or more occurences of -E. The argument -P specifies the maximum number of processors to use. It can be omitted, in which case all CPUs will be used.
Here, we show a few examples of the usage of run_experiment_families.py. The full specification can be found by running:
python3 run_experiment_families.py --helpor if needed also:
python3 complexity_experiment.py --helpSay we want to simulate an interferometer on
python3 run_experiment_families.py \
-E "-m 5 -ell 1,2,3 -n 1,1,2,0,0 -rep 100 -no-N -- -wA -thr -p" \
-E "-m 5 -ell 1,2,3 -n 1,1,2,0,0 -rep 100 -no-N -- -wN -LP -Nh paths -p" \
-P 10Above, the arguments within -E are divided into two parts, separated by --. The first part contains arguments to the experiment scheduler itself, while the second part contains arguments passed directly to the complexity experiment code (see description of the layers above).
In this example, the scheduler arguments (before --) are:
-
-m 5the number of modes$m = 5$ , -
-ell 1,2,3the loop lengths$\underline\ell = (1,2,3)$ , notice the comma-separated values, -
-n 1,1,2,0,0the input state$\ket{\underline n} = \ket{1,1,2,0,0}$ in the number (mode occupation) basis, with a photon each in the first two modes, two photons in mode 2, and zero elsewhere, -
-rep 100number of samples per experiment, -
-no-Nsaying we do not want to generate a sample for each possible measurement outcome$\ket{\underline N}$ . If omitted, the scheduler will run an experiment instance for each possible$\ket{\underline N}$ , postselecting on that outcome to compute its complexity. In most cases, we recommend using-no-Nwhich selects outcomes using true amplitudes or a heuristic probability (see below).
The arguments passed directly to the complexity simulator (after --) are:
- in the first line with
-Eabove:-
-wArun fullwavefunction simulator, i.e. compute trueAmplitudes, -
-thrbeamsplitter angles$\{\theta_i\}_i$ (th) are chosenrandomly in each instance; seecomplexity_experiment.py --helpfor other options of selecting$\{ \theta_i \}_i$ -
-puseprogressive decomposition.
-
- in the second line:
-
-wNdo not performwavefunction simulation, i.e. statevector isNot computed, -
-LPcompute theLatticePath diagram evolution instead, -
-Nh pathschoose the measurement outcome$\ket{\underline N}$ using theheuristic probability called here (lattice)paths.
-
Now we run a more complex example, more in the spirit of the experiments used in the paper (see the notebook); though a little different to show the framework.
We simulate interferometers with loop lengths
python3 run_experiment_families.py \
-E "-m m -ell 1,l,ll -rep 100 -no-N -r m=R:281:10 -r l=1:6 -e ll=l*l -e R=2+l+ll -- -wN -LP -Nh paths -p"Above:
-
-m mmeans the number of modes in an experiment will be defined by a variablem, -
-ell 1,l,llmeans the loop lengths are given by 1, variablel, and variablell, -
-r m=R:281:10defines a variablemtaking the values inrange(R, 281, 10)in the Python sense, i.e.$R \le m < 281$ (note never equal to 281), and taking steps of size 10, -
-r l=1:6defines a variableltaking values inrange(1, 6), i.e.$l = { 1, 2, \dots, 5 }$ -
-e ll=l*ldefines a variablellthat, in each instance, evaluates tol*l, -
-e R=2+l+lldefine a variableRthat, in each instance, evaluates to2+l+ll, - the absence of
-nimplies the default input state$\ket{\underline n} = \ket{1,0,1,0,\dots,1,0,(1)}$ .
The variable/evaluation framework is intentionally limited. Variable names must match the regular expression [a-zA-Z]+, and they can be used only in -m, -ell, -e, -r.
The range definition (-r) syntax is VAR=START:STOP[:STEP] and the semantics are those of Python's range. The evaluation (-e) allows only basic arithmetic, however it will execute code.
The utilities, as used above, will create two subdirectories in the current working directory:
logs/— the scheduler threads (if using multiple CPUs) will write logs saying what experiments they are running, and where the output data can be found. If errors occur, these will be found here as well.experiments/— the complexity experiment families will each get a subdirectory here, by default identified by the start time and a random string. Each such subdirectory will contain output data from individual runs of that experiment family, as json files. At the moment, these contain a lot of information by default. See in the notebook how to process this data.
In order to see the full specification of the scheduler, call:
python3 run_experiment_families.py --helpIn order to see the full specification of the complexity experiment code itself, in particular arguments that may go after -- in the above examples, call:
python3 complexity_experiment.py --helpNote that some arguments to complexity_experiment.py are passed by the scheduler run_experiment_families.py, and should not be passed in -E "... -- <here>" unless you specifically want to overwrite them.