SOQCS Benchmark

In this example various random circuits of N photons and 2N channels are generated. The N photons are assigned one by one to be initialized in the first N channels. The amplitude to find out those photons in the same configuration at the output is calculated. The calculation of this amplitude implies the calculation of a single permanent. The time required to calculate this permanent with different methods is registered and plotted as function of the number of photons and channels. The permanent is calculated using the the Balasubramanian–Bax–Franklin–Glynn formula “Glynn”, the Ryser formula “Ryser” or the Ryser formula making use of parallelization in the way suggested in ref. [1] “Ryser 10”. In the last case 10 processor cores are used.

[1] P.H. Lundow, K. Markström, Efficient computation of permanents, with applications to Boson sampling and random matrices, Journal of Computational Physics, Volume 455, 2022,110990.

[1]:
import soqcs  # SOQCS Library
import time   # Time measurement library

Set up simulation constant and create the simulator.

[2]:
# Configuration constants
minnph  = 10       # Minimum number of photons
maxnph  = 20       # Maximum number of photons
chf     = 2        # Channels by photon

# Create the simulator
sim = soqcs.simulator(1)

The next piece of code performs the benchmark for the different methods mentioned above. Random circuits are generated to calculate these benchmarks from minph photons to maxnph photon doubling the number of channels with respect the number of photons.

[3]:
print("  nph   nch    Glynn    Ryser  Ryser10")
for nph in range (minnph,maxnph+1):
    nch=chf*nph;

    # Build circuit
    example = soqcs.qodev(nph,nch)
    for j in range (0,nph):
        example.add_photons(1,j)
        example.random_circuit()
    for j in range (0,nch):
        example.detector(j)

    # Set-up inital state
    inputst=example.input()
    # List of output amplitudes to be calcualted
    olist=example.input()
    # Set-up circuit
    circuit=example.circuit()

    # Simulate Glynn
    start = time.time()
    output=sim.run_st(inputst,circuit,2,st_list=olist);
    end = time.time()
    tglynn=(end-start)*1000

    # Simulate Ryser 1
    start = time.time()
    output=sim.run_st(inputst,circuit,4,nthreads=1,st_list=olist);
    end = time.time()
    tryser=(end-start)*1000

    # Simulate Ryser 10
    start = time.time()
    output=sim.run_st(inputst,circuit,4,nthreads=10,st_list=olist);
    end = time.time()
    tryser10=(end-start)*1000

    # Print results
    print("{:5d}".format(nph),"{:5d}".format(nch),"{:8.2f}".format(tglynn),"{:8.2f}".format(tryser),"{:8.2f}".format(tryser10))
  nph   nch    Glynn    Ryser  Ryser10
   10    20     0.07     1.14     0.04
   11    22     0.17     0.11     0.03
   12    24     0.35     0.21     0.04
   13    26     0.69     0.44     0.07
   14    28     1.38     0.88     0.13
   15    30     2.90     1.87     0.25
   16    32     5.81     3.53     0.49
   17    34    11.45     6.82     0.90
   18    36    22.04    14.43     1.94
   19    38    46.05    36.39     7.57
   20    40   112.97   104.44    13.10

THIS CODE IS PART OF SOQCS

Copyright: Copyright © 2023 National University of Ireland Maynooth, Maynooth University. All rights reserved. The contents and use of this document and the related code are subject to the licence terms detailed in LICENCE.txt