<jupyter_start><jupyter_text>Simulation of a GBS experiment In this notebook, we calculate the vibronic spectrum of $V_3$ using a sampling method, simulating a Gaussian Boson Sampling experiment. We will use `StrawberryFields` for the simulation. "Strawberry Fields" is a code created by Xanadu and is the driver behind GBS. This can be installed using **pip**, but see install instructions in the  Project 3 Landing Page. First, let us import necessary packages<jupyter_code>from sys import argv
from strawberryfields.apps import vibronic, data, sample, plot
import numpy as np
from common.utils import get_state, plot_spectrum, plot_spectrum_from_samples
# from plotly import offline
# offline.init_notebook_mode(connected = True)<jupyter_output><empty_output><jupyter_text>The `FC.cxx` programm we looked at in the previous notebook, does some intermediate calculations which carry necessary information for the input to GBS. We modified the `FC.cxx` a bit (see the code after the comment line "start writing the file for GBS") to output all the required information into a text file Variables. After compiling and executing this code, we have the necessary file to feed to GBS simulation. Let us first declare some variables<jupyter_code># inputfile = open(argv[1], "r")
inputfile = open("common/FC/output/V3.duschinsky.out", "r")

N=int(inputfile.readline())     #Number of Atoms
nmodes=3*N-6                    #Number of Modes

w=np.zeros(nmodes,float)        #vib. frequencies of ground electronic state
wp=np.zeros(nmodes,float)       #vib. frequencies of excited electronic state
Ud=np.zeros((nmodes,nmodes),float)   #Duschinsky Matrix
delta=np.zeros(nmodes,float)    #Displacement Vector

T = 500  # temperature<jupyter_output><empty_output><jupyter_text>Read in Parameters.The code below assumes, that the input file has the following structure```1 line: number of atoms1 line: space-separated list of normal frequencies of the ground state1 line: space-separated list of normal frequencies of the excited statenmodes lines: each line space-separated numbers representing a row in Duschinsky matrix1 line: space-separated list of displacements```<jupyter_code>w = np.array([float(x) for x in inputfile.readline().split()])
wp = np.array([float(x) for x in inputfile.readline().split()])
for i in range(nmodes):
    Ud[i, :] = np.array([float(x) for x in inputfile.readline().split()])
delta = np.array([float(x) for x in inputfile.readline().split()])<jupyter_output><empty_output><jupyter_text>Use "Strawberry Fields" to calculate GBS Parameters based on the frequencies, Duschinsky matrix, and temperature that was provided as input.<jupyter_code>t, U1, r, U2, alpha = vibronic.gbs_params(w, wp, Ud, delta, T)<jupyter_output><empty_output><jupyter_text>Generate Samples and Calculate Energies of Samples.Note: The number of samples may be changed if the spectrum is not converged.<jupyter_code>nr_samples = 1000
s = sample.vibronic(t, U1, r, U2, alpha, nr_samples)
e = vibronic.energies(s, w, wp)<jupyter_output><empty_output><jupyter_text>To plot the spectrum we use the function `plot_spectrum_from_samples` we have implemented in `common/utils.py`, which is using matplotlib to do the plotting.<jupyter_code># spectrum = plot.spectrum(e, xmin=-1000, xmax=2000)
# offline.iplot(spectrum)

plot_desc = {'title': "Vibronic spectrum ($V_3$)", 'xlabel': "Energy ($cm^{-1}$)", 'ylabel': "Counts"}
plot_spectrum_from_samples(e, plot_desc, gamma=50.0)<jupyter_output><empty_output><jupyter_text>Generally, since we are doing a sampling here, the more samples the better. We need a lot of samples to reconstruct the occurance probabilites of output photon counting events. If one runs this algorithm for various number of samples, one will see, that the spectrum undergoes some changes with the addition of more and more samples. The height of the peaks may change, new peaks may appaer. However as the number gets larger and large, the picture tends to become stable, and at this point we can conclude, that we have successfully reconstructed the FCF spectrom from the GBS device. Our tests show, that in the particular case of $V_3$ molecule above a few handreds of samples are already enough to reconsrtuct the spectrum. See below for further details.  Challenge 1Instead of simulating a sampling procedure from a photonic devie and approximating the probabilities of output energies based on the sampling results, we can compute the exact probabilities using loop hafnians. Ideally, we would calculate the exact probabilities of all possible output patterns and construct the spectrum based on this exact probability distribution. For each output pattern we will need to calculate a loop hafnian. With increasing photon numbers this calculations become intractable, since 1. The loop hafnian is exponentially hard to calculate on a classical computer, 2. The number of output patters becomes exponentially many. So, instead of calculating the entire probability distribution exactly, we will just calculate the exact probabilities for patterns which are supposed to have high probability (and significant contribution in the spectrum), which we got in the previous step, while sampling the GBS device.<jupyter_code>s_unique = list(set([tuple(item) for item in s]))
s_unique = [list(x) for x in s_unique]

e_unique = vibronic.energies(s_unique, w, wp)

state = get_state(t, U1, r, U2, alpha)
probs = [state.fock_prob(pattern, cutoff=20) for pattern in s_unique]<jupyter_output><empty_output><jupyter_text>And we plot the result. As we can see from the comparison of this plot with the one above, we can see, that the shape of the spectrum does not change when we use exact probabilities, which means the sampling version was pretty accurate already.<jupyter_code>plot_desc['ylabel'] = "Probabilities"
plot_spectrum(np.vstack([e_unique, probs]), plot_desc, gamma=50.0)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07549085985104942, 'fraction_numerical': 0.007616790792146243, 'mean_word_length': 5.691959229898075, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '605237', 'license': 'MIT', 'n_tokens_mistral': 1713, 'n_tokens_neox': 1626, 'n_words': 728, 'path': 'Project_3_Franck_Condon_Factors/Task3.ipynb', 'repo_name': 'QuantumCDL2020C-week4Group5/CohortProject_2020', 'size': '5908'}