From a25248df3fd70d111d76f7a686d7e59056893367 Mon Sep 17 00:00:00 2001
From: soupe06 <92365789+soupe06@users.noreply.github.com>
Date: Fri, 25 Apr 2025 18:12:45 +0200
Subject: [PATCH] Add files via upload
---
Boson_sampling_TO_DO.ipynb | 48904 ++++++++++++++++
Boson_sampling_answers.ipynb | 48888 +++++++++++++++
Differential_equation_resolution_TO_DO.ipynb | 651 +
...erential_equation_resolution_answers.ipynb | 643 +
One-qubit_and_two-qubit_gates_TO_DO.ipynb | 831 +
One-qubit_and_two-qubit_gates_answers.ipynb | 1023 +
6 files changed, 100940 insertions(+)
create mode 100644 Boson_sampling_TO_DO.ipynb
create mode 100644 Boson_sampling_answers.ipynb
create mode 100644 Differential_equation_resolution_TO_DO.ipynb
create mode 100644 Differential_equation_resolution_answers.ipynb
create mode 100644 One-qubit_and_two-qubit_gates_TO_DO.ipynb
create mode 100644 One-qubit_and_two-qubit_gates_answers.ipynb
diff --git a/Boson_sampling_TO_DO.ipynb b/Boson_sampling_TO_DO.ipynb
new file mode 100644
index 0000000..efa871c
--- /dev/null
+++ b/Boson_sampling_TO_DO.ipynb
@@ -0,0 +1,48904 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "1c11286e",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dad5a69d",
+ "metadata": {},
+ "source": [
+ "### Boson sampling"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "89e1f822",
+ "metadata": {},
+ "source": [
+ "Sampling is the problem of selecting data from a large set, usually to find a smaller set of data that is representative of the entire set. Naturally, as problem sizes grow, these types of problems become intractable for classical computers. This means that even if we are able to find a solution to our problem, the time it takes us to do so will be too long, deeming the solution no longer useful to us.\n",
+ "\n",
+ "In Perceval, we use photons as our bosons (indistinguishable subatomic particles with an integer spin) to perform the task of boson sampling. Boson sampling is a quantum sampling problem, drawing from a big probability distribution of output states of a system. As our knowledge of the quantum world grows and quantum hardware becomes better, we hope to offer solutions to problems previously thought intractable."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d38c01f3",
+ "metadata": {},
+ "source": [
+ "We are interested to simulate a boson sample with 14 photons and 60 modes, order of size comparable to what was done in Boson Sampling with 20 Input Photons and a 60-Mode Interferometer in a $10^{14}$-Dimensional Hilbert Space [1]."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "dede995f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from collections import Counter\n",
+ "import gzip\n",
+ "import pickle\n",
+ "import time\n",
+ "import random\n",
+ "import perceval as pcvl\n",
+ "from perceval.algorithm import Sampler"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84be34da",
+ "metadata": {},
+ "source": [
+ "#### Boson sampling with a perfect source"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7ea02d3b",
+ "metadata": {},
+ "source": [
+ "Let's define all the required values below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "ea14f365",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n = 14 #number of photons at the input\n",
+ "m = 60 #number of modes\n",
+ "N = 5000000 #number of samplings we want in the end"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "75e1ee98",
+ "metadata": {},
+ "source": [
+ "Now we can generate a Haar random unitary with Perceval."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "21e960f7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Unitary_60 = pcvl.Matrix.random_unitary(m) #creates a random unitary of dimension 60"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7d6ca6fb",
+ "metadata": {},
+ "source": [
+ "To be able to decompose this unitary, first we have to choose a set of optical components we will use to do. The Mach-Zehnder interferometer (MZI) is a good choice as it is composed of only 2 beam splitters and 2 phase shifters and it is highly configurable."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "19234775",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# TO DO: build your MZI - for this you will need a beam splitter, then a phase shifter on\n",
+ "# mode 0 and another beam splitter and then a phase shifter on mode 1\n",
+ "# HINT: Since we will be decomposing our unitary, don't give values to the parameters in the circuit.\n",
+ "# The beam splitters can remain in the default Rx gate convention and the phase shifters'\n",
+ "# parameters can be left undefined by using pcvl.Parameter(\"name_of_parameter\").\n",
+ "# Remember to name your two phi parameters differently!\n",
+ "pcvl.pdisplay(mzi) #display your MZI and check if it looks as described above"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "eb27d276",
+ "metadata": {},
+ "source": [
+ "No we can decompose the unitary into a set of MZIs using Reck's (traingular) scheme [2]. Naturally, since the matrix dimension is 60, this will be a huge circuit and may take some time to compile."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "bc9e5566",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Linear_Circuit_60 = pcvl.Circuit.decomposition(Unitary_60, mzi, phase_shifter_fn=pcvl.PS, shape=\"triangle\")\n",
+ "pcvl.pdisplay(Linear_Circuit_60)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "41aed0bb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# You can see the circuit is shaped like a triangle, this cuircuit composition is called the Reck scheme.\n",
+ "# TO DO: Test to see how the circuit composition looks like without the variable 'shape' defined.\n",
+ "# Do this with a smaller sized matrix to save time."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7d6ac933",
+ "metadata": {},
+ "source": [
+ "#### Running simulation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cd1e829a",
+ "metadata": {},
+ "source": [
+ "Now we can choose the way to perform the simulation of boson sampling with Perceval. The number of photons is within what we could simulate with the Naive backend, however the output space is far too big just to enumerate and store the states so we chose the CliffordClifford2017 backend instead. We encourage you to check out our multiple simulation backend options and their performance comparison on different types of problems available to view on the Perceval documentation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "a23c2a44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "QPU = pcvl.Processor(\"CliffordClifford2017\", Linear_Circuit_60)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e6a25f2",
+ "metadata": {},
+ "source": [
+ "Since this isn't a real problem and we are just trying to show the power of quantum computing when it comes to difficult problems to solve, such as boson sampling, we don't care what the input to our circuit is and can choose a random one."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "6ac056ec",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The input state: |0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,0>\n"
+ ]
+ }
+ ],
+ "source": [
+ "def generate_input(n, m, modes = None):\n",
+ " \"This function randomly chooses an input with n photons in m modes.\"\n",
+ " if modes == None : #the function works with a given number of modes m, otherwise selecting them randomly\n",
+ " modes = sorted(random.sample(range(m),n))\n",
+ " state = \"|\"\n",
+ " for i in range(m):\n",
+ " state = state + \"0\"*(1 - (i in modes)) +\"1\"*(i in modes)+ \",\"*(i < m-1)\n",
+ " return pcvl.BasicState(state + \">\")\n",
+ "\n",
+ "input_state = generate_input(n, m)\n",
+ "print(\"The input state: \", input_state)\n",
+ "\n",
+ "# TO DO: Provide the processor with the input state defined above."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "faf263ef",
+ "metadata": {},
+ "source": [
+ "Using this input, our output states are states composed of n photons in m modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "d6b24894",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The sampled outputs are:\n",
+ "|0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,0,2,0,0,0,0,0,0,0,1,2,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0>\n",
+ "|0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0>\n",
+ "|1,0,0,1,0,0,0,2,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0>\n",
+ "|0,0,0,1,0,0,0,3,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0>\n",
+ "|0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,2,1,0,0,0,0,0,0,0,0,0>\n",
+ "|1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1>\n",
+ "|1,1,1,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,1,0,0,0,0,0,0,0,1,0,0,0>\n",
+ "|0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0>\n",
+ "|0,0,2,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,1,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0>\n",
+ "|0,0,0,1,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,2,0,1,0,0,1,0,0>\n"
+ ]
+ }
+ ],
+ "source": [
+ "QPU.min_detected_photons_filter(0) #we're telling the processor that we want to keep all outputs\n",
+ "# TO DO: What happens when you change the number you're filtering with? Can you filter by a number\n",
+ "# higher than the number of photons in the input state? Why?\n",
+ "\n",
+ "sampler = Sampler(QPU)\n",
+ "\n",
+ "print(\"The sampled outputs are:\")\n",
+ "for out_state in sampler.samples(10)[\"results\"]:\n",
+ " print(out_state)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "263d2ba0",
+ "metadata": {},
+ "source": [
+ "Now we can also perform boson sampling N times. This will take some time so let's save the results to a file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "9cf2a385",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# if we want to launch parallel process\n",
+ "worker_id=1\n",
+ "\n",
+ "#store the input and the unitary\n",
+ "with open(\"%dphotons_%dmodes_%dsamples-worker%s-unitary.pkl\" %(n,m,N,worker_id), 'wb') as f:\n",
+ " pickle.dump(Unitary_60, f)\n",
+ "\n",
+ "with open(\"%dphotons_%dmodes_%dsamples-worker%s-inputstate.pkl\" %(n,m,N,worker_id), 'w') as f:\n",
+ " f.write(str(input_state)+\"\\n\")\n",
+ "\n",
+ "with gzip.open(\"%dphotons_%dmodes_%dsamples-worker%s-samples.txt.gz\" %(n,m,N,worker_id), 'wb') as f:\n",
+ " start = time.time()\n",
+ " for _ in range(N):\n",
+ " f.write((str(sampler.samples(1)[\"results\"][0])+\"\\n\").encode())\n",
+ " end = time.time()\n",
+ " f.write(str(\"==> %d\\n\" % (end-start)).encode())\n",
+ "f.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5d207441",
+ "metadata": {},
+ "source": [
+ "A little after (4 hours on a 3.1GHz Intel) - we do have 5M samples. We launched this on 32 threads for 2 days and collected 300 batches of 5M samples.\n",
+ "\n",
+ "Let us analyze the K-first mode bunching on these samples."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a1062d81",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "worker_id = 1\n",
+ "count = 0\n",
+ "bunching_distribution = Counter()\n",
+ "\n",
+ "with gzip.open(\"%dphotons_%dmodes_%dsamples-worker%s-samples.txt.gz\"%(n,m,N,worker_id), \"rt\") as f:\n",
+ " for l in f:\n",
+ " l = l.strip()\n",
+ " if l.startswith(\"|\") and l.endswith(\">\"):\n",
+ " try:\n",
+ " st = pcvl.BasicState(l)\n",
+ " count+=1\n",
+ " bunching_distribution[st.photon2mode(st.n-1)]+=1\n",
+ " except Exception:\n",
+ " pass\n",
+ "print(count, \"samples\")\n",
+ "print(\"Bunching Distribution:\", \"\\t\".join([str(bunching_distribution[k]) for k in range(m)]))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "576eb79b",
+ "metadata": {},
+ "source": [
+ "These numbers have been used on 300 samples for certification - see our article on Perceval for more details."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5a2ced3a",
+ "metadata": {},
+ "source": [
+ "#### Boson sampling with a non perfect source"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a95e1907",
+ "metadata": {},
+ "source": [
+ "Let's perform Boson sampling with a non perfect source. We declare a source with 90% brightness and purity. Here, we would reach the limits of the simulation if we use the same input as before, as for each photon at the entrance, we multiply by 3 the number of input states (0, 1 or 2 photons at the input), leading to $3^n$ states."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5c6bf7c1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "3 ** n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fb96c9b6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "source = pcvl.Source(emission_probability=0.9, multiphoton_component=0.1)\n",
+ "QPU = pcvl.Processor(\"CliffordClifford2017\", Linear_Circuit_60, source)\n",
+ "QPU.with_input(pcvl.BasicState([0, 1, 1] + (m - 3) * [0])) #notice the change in input"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0216f7e4",
+ "metadata": {},
+ "source": [
+ "Computing the other way around, we can now check the source distribution of the processor to see how likely a state at the input of the linear circuit will be."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a8965f49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pcvl.pdisplay(QPU.source_distribution, precision=1e-7, max_v=20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53795d58",
+ "metadata": {},
+ "source": [
+ "As expected, the most likely state to have been the input of the circuit was in fact the input we provided it with.\n",
+ "\n",
+ "Now we can launch the entire computation again starting from cell 8 to use this imperfect source QPU with the same nominal input, or from cell 7 for another random input."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84b2a6a9",
+ "metadata": {},
+ "source": [
+ "### References"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "811e4838",
+ "metadata": {},
+ "source": [
+ "[1] Hui Wang, et al. Boson Sampling with 20 Input Photons and a 60-Mode Interferometer in a $10^{14}$-Dimensional Hilbert Space. Physical Review Letters, 123(25):250503, December 2019. Publisher: American Physical Society.\n",
+ "\n",
+ "[2] Michael Reck, Anton Zeilinger, Herbert J Bernstein, and Philip Bertani. Experimental realization of any discrete unitary operator. Physical review letters, 73(1):58, 1994."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Boson_sampling_answers.ipynb b/Boson_sampling_answers.ipynb
new file mode 100644
index 0000000..189a010
--- /dev/null
+++ b/Boson_sampling_answers.ipynb
@@ -0,0 +1,48888 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "1c11286e",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "dad5a69d",
+ "metadata": {},
+ "source": [
+ "### Boson sampling"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "89e1f822",
+ "metadata": {},
+ "source": [
+ "Sampling is the problem of selecting data from a large set, usually to find a smaller set of data that is representative of the entire set. Naturally, as problem sizes grow, these types of problems become intractable for classical computers. This means that even if we are able to find a solution to our problem, the time it takes us to do so will be too long, deeming the solution no longer useful to us.\n",
+ "\n",
+ "In Perceval, we use photons as our bosons (indistinguishable subatomic particles with an integer spin) to perform the task of boson sampling. Boson sampling is a quantum sampling problem, drawing from a big probability distribution of output states of a system. As our knowledge of the quantum world grows and quantum hardware becomes better, we hope to offer solutions to problems previously thought intractable."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d38c01f3",
+ "metadata": {},
+ "source": [
+ "We are interested to simulate a boson sample with 14 photons and 60 modes, order of size comparable to what was done in Boson Sampling with 20 Input Photons and a 60-Mode Interferometer in a $10^{14}$-Dimensional Hilbert Space [1]."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "dede995f",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from collections import Counter\n",
+ "import gzip\n",
+ "import pickle\n",
+ "import time\n",
+ "import random\n",
+ "import perceval as pcvl\n",
+ "from perceval.algorithm import Sampler"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84be34da",
+ "metadata": {},
+ "source": [
+ "#### Boson sampling with a perfect source"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7ea02d3b",
+ "metadata": {},
+ "source": [
+ "Let's define all the required values below."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "ea14f365",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "n = 14 #number of photons at the input\n",
+ "m = 60 #number of modes\n",
+ "N = 5000000 #number of samplings we want in the end"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "75e1ee98",
+ "metadata": {},
+ "source": [
+ "Now we can generate a Haar random unitary with Perceval."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "21e960f7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Unitary_60 = pcvl.Matrix.random_unitary(m) #creates a random unitary of dimension 60"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7d6ca6fb",
+ "metadata": {},
+ "source": [
+ "To be able to decompose this unitary, first we have to choose a set of optical components we will use to do. The Mach-Zehnder interferometer (MZI) is a good choice as it is composed of only 2 beam splitters and 2 phase shifters and it is highly configurable."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "19234775",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mzi = (pcvl.BS() // (0, pcvl.PS(phi=pcvl.Parameter(\"φ_a\")))\n",
+ " // pcvl.BS() // (1, pcvl.PS(phi=pcvl.Parameter(\"φ_b\"))))\n",
+ "pcvl.pdisplay(mzi)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "eb27d276",
+ "metadata": {},
+ "source": [
+ "No we can decompose the unitary into a set of MZIs using Reck's (traingular) scheme [2]. Naturally, since the matrix dimension is 60, this will be a huge circuit and may take some time to compile."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "bc9e5566",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Linear_Circuit_60 = pcvl.Circuit.decomposition(Unitary_60, mzi, phase_shifter_fn=pcvl.PS, shape=\"triangle\")\n",
+ "pcvl.pdisplay(Linear_Circuit_60)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7d6ac933",
+ "metadata": {},
+ "source": [
+ "#### Running simulation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cd1e829a",
+ "metadata": {},
+ "source": [
+ "Now we can choose the way to perform the simulation of boson sampling with Perceval. The number of photons is within what we could simulate with the Naive backend, however the output space is far too big just to enumerate and store the states so we chose the CliffordClifford2017 backend instead. We encourage you to check out our multiple simulation backend options and their performance comparison on different types of problems available to view on the Perceval documentation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "a23c2a44",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "QPU = pcvl.Processor(\"CliffordClifford2017\", Linear_Circuit_60)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0e6a25f2",
+ "metadata": {},
+ "source": [
+ "Since this isn't a real problem and we are just trying to show the power of quantum computing when it comes to difficult problems to solve, such as boson sampling, we don't care what the input to our circuit is and can choose a random one."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "6ac056ec",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The input state: |0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,1,0>\n"
+ ]
+ }
+ ],
+ "source": [
+ "def generate_input(n, m, modes = None):\n",
+ " \"This function randomly chooses an input with n photons in m modes.\"\n",
+ " if modes == None : #the function works with a given number of modes m, otherwise selecting them randomly\n",
+ " modes = sorted(random.sample(range(m),n))\n",
+ " state = \"|\"\n",
+ " for i in range(m):\n",
+ " state = state + \"0\"*(1 - (i in modes)) +\"1\"*(i in modes)+ \",\"*(i < m-1)\n",
+ " return pcvl.BasicState(state + \">\")\n",
+ "\n",
+ "input_state = generate_input(n, m)\n",
+ "print(\"The input state: \", input_state)\n",
+ "QPU.with_input(input_state) #giving the processor the input state"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "faf263ef",
+ "metadata": {},
+ "source": [
+ "Using this input, our output states are states composed of n photons in m modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "d6b24894",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "The sampled outputs are:\n",
+ "|0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,0,2,0,0,0,0,0,0,0,1,2,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0>\n",
+ "|0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0>\n",
+ "|1,0,0,1,0,0,0,2,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0>\n",
+ "|0,0,0,1,0,0,0,3,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0>\n",
+ "|0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,2,1,0,0,0,0,0,0,0,0,0>\n",
+ "|1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1>\n",
+ "|1,1,1,0,1,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,1,0,0,0,0,0,0,0,1,0,0,0>\n",
+ "|0,0,1,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0>\n",
+ "|0,0,2,0,0,3,0,0,1,0,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,1,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0>\n",
+ "|0,0,0,1,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,2,0,1,0,0,1,0,0>\n"
+ ]
+ }
+ ],
+ "source": [
+ "QPU.min_detected_photons_filter(0) #we're telling the processor that we want to keep all outputs\n",
+ "# We're telling Perceval that we need *at least* 0 photons in our output, thus we will keep all\n",
+ "# possible outputs. Naturally, we cannot observe more photons in the output than there were in the\n",
+ "# input so we'll never be able to filter by a number higher than the number of photons in the input.\n",
+ "\n",
+ "sampler = Sampler(QPU)\n",
+ "\n",
+ "print(\"The sampled outputs are:\")\n",
+ "for out_state in sampler.samples(10)[\"results\"]:\n",
+ " print(out_state)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "263d2ba0",
+ "metadata": {},
+ "source": [
+ "Now we can also perform boson sampling N times. This will take some time so let's save the results to a file."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "9cf2a385",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# if we want to launch parallel process\n",
+ "worker_id=1\n",
+ "\n",
+ "#store the input and the unitary\n",
+ "with open(\"%dphotons_%dmodes_%dsamples-worker%s-unitary.pkl\" %(n,m,N,worker_id), 'wb') as f:\n",
+ " pickle.dump(Unitary_60, f)\n",
+ "\n",
+ "with open(\"%dphotons_%dmodes_%dsamples-worker%s-inputstate.pkl\" %(n,m,N,worker_id), 'w') as f:\n",
+ " f.write(str(input_state)+\"\\n\")\n",
+ "\n",
+ "with gzip.open(\"%dphotons_%dmodes_%dsamples-worker%s-samples.txt.gz\" %(n,m,N,worker_id), 'wb') as f:\n",
+ " start = time.time()\n",
+ " for _ in range(N):\n",
+ " f.write((str(sampler.samples(1)[\"results\"][0])+\"\\n\").encode())\n",
+ " end = time.time()\n",
+ " f.write(str(\"==> %d\\n\" % (end-start)).encode())\n",
+ "f.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5d207441",
+ "metadata": {},
+ "source": [
+ "A little after (4 hours on a 3.1GHz Intel) - we do have 5M samples. We launched this on 32 threads for 2 days and collected 300 batches of 5M samples.\n",
+ "\n",
+ "Let us analyze the K-first mode bunching on these samples."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a1062d81",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "worker_id = 1\n",
+ "count = 0\n",
+ "bunching_distribution = Counter()\n",
+ "\n",
+ "with gzip.open(\"%dphotons_%dmodes_%dsamples-worker%s-samples.txt.gz\"%(n,m,N,worker_id), \"rt\") as f:\n",
+ " for l in f:\n",
+ " l = l.strip()\n",
+ " if l.startswith(\"|\") and l.endswith(\">\"):\n",
+ " try:\n",
+ " st = pcvl.BasicState(l)\n",
+ " count+=1\n",
+ " bunching_distribution[st.photon2mode(st.n-1)]+=1\n",
+ " except Exception:\n",
+ " pass\n",
+ "print(count, \"samples\")\n",
+ "print(\"Bunching Distribution:\", \"\\t\".join([str(bunching_distribution[k]) for k in range(m)]))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "576eb79b",
+ "metadata": {},
+ "source": [
+ "These numbers have been used on 300 samples for certification - see our article on Perceval for more details."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5a2ced3a",
+ "metadata": {},
+ "source": [
+ "#### Boson sampling with a non perfect source"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a95e1907",
+ "metadata": {},
+ "source": [
+ "Let's perform Boson sampling with a non perfect source. We declare a source with 90% brightness and purity. Here, we would reach the limits of the simulation if we use the same input as before, as for each photon at the entrance, we multiply by 3 the number of input states (0, 1 or 2 photons at the input), leading to $3^n$ states."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5c6bf7c1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "3 ** n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "fb96c9b6",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "source = pcvl.Source(emission_probability=0.9, multiphoton_component=0.1)\n",
+ "QPU = pcvl.Processor(\"CliffordClifford2017\", Linear_Circuit_60, source)\n",
+ "QPU.with_input(pcvl.BasicState([0, 1, 1] + (m - 3) * [0])) #notice the change in input"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0216f7e4",
+ "metadata": {},
+ "source": [
+ "Computing the other way around, we can now check the source distribution of the processor to see how likely a state at the input of the linear circuit will be."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a8965f49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "pcvl.pdisplay(QPU.source_distribution, precision=1e-7, max_v=20)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "53795d58",
+ "metadata": {},
+ "source": [
+ "As expected, the most likely state to have been the input of the circuit was in fact the input we provided it with.\n",
+ "\n",
+ "Now we can launch the entire computation again starting from cell 8 to use this imperfect source QPU with the same nominal input, or from cell 7 for another random input."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "84b2a6a9",
+ "metadata": {},
+ "source": [
+ "### References"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "811e4838",
+ "metadata": {},
+ "source": [
+ "[1] Hui Wang, et al. Boson Sampling with 20 Input Photons and a 60-Mode Interferometer in a $10^{14}$-Dimensional Hilbert Space. Physical Review Letters, 123(25):250503, December 2019. Publisher: American Physical Society.\n",
+ "\n",
+ "[2] Michael Reck, Anton Zeilinger, Herbert J Bernstein, and Philip Bertani. Experimental realization of any discrete unitary operator. Physical review letters, 73(1):58, 1994."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Differential_equation_resolution_TO_DO.ipynb b/Differential_equation_resolution_TO_DO.ipynb
new file mode 100644
index 0000000..12ec964
--- /dev/null
+++ b/Differential_equation_resolution_TO_DO.ipynb
@@ -0,0 +1,651 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "1c11286e",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b0c92f7",
+ "metadata": {},
+ "source": [
+ "### Differential equation resolution"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a74dd31d",
+ "metadata": {},
+ "source": [
+ "Differential equations are used to describe variables that continuously vary with respect to a change in other variables. These equations can be used to model the behaviours of complex systems. A simple example of this can be found in economics, where we wish to study the relationships between some variables and predict their future behaviours."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5726700a",
+ "metadata": {},
+ "source": [
+ "#### Introduction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e67d9ab4",
+ "metadata": {},
+ "source": [
+ "We present here a Perceval implementation of a Quantum Machine Learning algorithm for solving differential equations. Its aim is to approximate the solution to the differential equation considered in [1]:\n",
+ "\n",
+ "$$\\frac{df}{dx}+\\lambda f(x)(\\kappa+tan(\\lambda x))=0$$\n",
+ "\n",
+ "with boundary condition $f(0)=f_0$. The analytical solution is $f(x)=f_0\\;exp(-\\kappa \\lambda x) cos(\\lambda x)$."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f5b00399",
+ "metadata": {},
+ "source": [
+ "#### QML loss function definition"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c47833b5",
+ "metadata": {},
+ "source": [
+ "In order to use QML to solve this differential equation, we first need to derive a loss function from it whose minimum is associated to the differential equation's analytical solution.\n",
+ "\n",
+ "Let $F[\\{d^mf/dx^m\\}_m,f,x]=0$ be a general differential equation verified by $f(x)$, where $F[.]$ is an operator acting on $f(x)$, its derivatives and $x$. For the solving of a differential equation, the loss function described in [1] consists of two terms $$\\mathcal{L}_{\\theta}[\\{d^mg/dx^m\\}_m,g,x]=\\mathcal{L}_{\\theta}^{(diff)}[\\{d^mg/dx^m\\}_m,g,x]+\\mathcal{L}_{\\theta}^{(boundary)}[g,x].$$\n",
+ "\n",
+ "The first term $\\mathcal{L}_{\\theta}^{(diff)}$ corresponds to the differential equation which has been discretised over a fixed regular grid of M points noted $x_i$: $$\\mathcal{L}_{\\theta}^{(diff)}[\\{d^mg/dx^m\\}_m,g,x]=\\frac{1}{M}\\sum_{i=1}^{M}L(F[d_x^mg(x_i),g(x_i),x_i],0),$$\n",
+ "\n",
+ "where $L(a,b)=(a-b)^2$ is the squared distance between two arguments. The second term $\\mathcal{L}_{\\theta}^{(boundary)}$ is associated with the initial conditions of our desired solution. It is defined as: $$\\mathcal{L}_{\\theta}^{(boundary)}[g,x]=\\eta L(g(x_0),f_0),$$\n",
+ "\n",
+ "where $\\eta$ is the weight granted to the boundary condition and $f_0$ is given by $f(x_0)=f_0$.\n",
+ "\n",
+ "Given a function approximator $f^{(n)}(x,\\pmb{\\theta},\\pmb{\\lambda})$, the loss function above will be minimised using a classical algorithm, updating the parameters $\\pmb{\\theta}$ based on samples obtained using a quantum device."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3f075260",
+ "metadata": {},
+ "source": [
+ "#### Quantum circuit architecture"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52b0ae69",
+ "metadata": {},
+ "source": [
+ "The feature map used is presented in [2,3,4]. The quantum circuit architecture from [4] is expressed as $\\mathcal{U}(x,\\pmb{\\theta})=\\mathcal{W}^{(2)}(\\pmb{\\theta}_2)\\mathcal{S}(x)\\mathcal{W}^{(1)}(\\pmb{\\theta}_1)$. The phase-shift operator $\\mathcal{S}(x)$ incorporates the $x$ dependency of the function we wish to approximate. It is sandwiched between two universal interferometers $\\mathcal{W}^{(1)}(\\pmb{\\theta}_1)$ and $\\mathcal{W}^{(2)}(\\pmb{\\theta}_2)$, where the beam splitter parameters $\\pmb{\\theta}_1$ and $\\pmb{\\theta}_2$ of this mesh architecture are tunable to enable training of the circuit. The output measurement operator, noted $\\mathcal{M}(\\pmb{\\lambda})$ is the projection on the Fock states obtained using photon-number resolving detectors, multiplied by some coefficients $\\pmb{\\lambda}$ which can also be tunable. Formally, we have:\n",
+ "\n",
+ "$$ \\mathcal{M}(\\boldsymbol{\\lambda}) = \\sum_{\\mathbf{\\left | n^{(f)}\\right \\rangle}}\\lambda_{\\mathbf{\\left | n^{(f)}\\right \\rangle}}\\mathbf{\\left | n^{(f)}\\right \\rangle}\\mathbf{\\left \\langle n^{(f)}\\right |},\n",
+ "$$\n",
+ "\n",
+ "where the sum is taken over all $\\binom{n+m-1}{n}$ possible Fock states considering $n$ photons in $m$ modes. Let $\\mathbf{\\left | n^{(i)}\\right \\rangle} = \\left |n^{(i)}_1,n^{(i)}_2,\\dots,n^{(i)}_m\\right \\rangle$ be the input state consisting of $n$ photons where $n^{(i)}_j$ is the number of photons in input mode $j$. Given these elements, the circuit's output $f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})$ is given by the following expectation value:\n",
+ "\n",
+ "$$\n",
+ "f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})=\\left\\langle\\mathbf{n}^{(i)}\\left|\\mathcal{U}^{\\dagger}(x, \\boldsymbol{\\theta}) \\mathcal{M}(\\boldsymbol{\\lambda}) \\mathcal{U}(x, \\boldsymbol{\\theta})\\right| \\mathbf{n}^{(i)}\\right\\rangle.\n",
+ "$$\n",
+ "\n",
+ "This expression can be rewritten as the following Fourier series \\[4\\]\n",
+ "\n",
+ "$$\n",
+ "f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})=\\sum_{\\omega \\in \\Omega_{n}} c_{\\omega}(\\boldsymbol{\\theta}, \\boldsymbol{\\lambda}) e^{i \\omega x},\n",
+ "$$\n",
+ "\n",
+ "where $\\Omega_n = \\{-n, -n+1, \\dots, n-1, n \\}$ is the frequency spectrum one can reach with $n$ incoming photons and $\\{c_\\omega(\\boldsymbol{\\theta}, \\boldsymbol{\\lambda})\\}$ are the Fourier coefficients. The $\\boldsymbol{\\lambda}$ parameters are sampled randomly in the interval $[-a;a]$, with $a$ a randomly chosen integer. $f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})$ will serve as a function approximator for this chosen differential equation. Differentiation in the loss function is discretised as $\\frac{df}{dx} \\simeq \\frac{f(x+\\Delta x) - f(x-\\Delta x)}{2\\Delta x}$.\n",
+ "\n",
+ "$n, m,$ and $\\boldsymbol{\\lambda}$ are variable parameters defined below. $\\Delta x$ is the mesh size."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "664403cb",
+ "metadata": {},
+ "source": [
+ "## Perceval Simulation\n",
+ "\n",
+ "### Initialisation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "cb1aca2a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import perceval as pcvl\n",
+ "import numpy as np\n",
+ "from math import comb\n",
+ "from scipy.optimize import minimize\n",
+ "import time\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib as mpl\n",
+ "import tqdm as tqdm"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b966a90",
+ "metadata": {},
+ "source": [
+ "We will run this notebook with 4 photons. We could use more photons, but the result with 4 photons is already satisfying."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "83c1de63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nphotons = 4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77763a57",
+ "metadata": {},
+ "source": [
+ "### Differential equation parameters\n",
+ "\n",
+ "We define here the value of the differential equation parameters and boundary condition $\\lambda, \\kappa, f_0$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "266fa65b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Differential equation parameters\n",
+ "lambd = 8\n",
+ "kappa = 0.1\n",
+ "\n",
+ "def F(u_prime, u, x): # DE, works with numpy arrays\n",
+ " return u_prime + lambd * u * (kappa + np.tan(lambd * x))\n",
+ "\n",
+ "# Boundary condition (f(x_0)=f_0)\n",
+ "x_0 = 0\n",
+ "f_0 = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "057a3ae0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Modeling parameters\n",
+ "n_grid = 50 # number of grid points of the discretized differential equation\n",
+ "range_min = 0 # minimum of the interval on which we wish to approximate our function\n",
+ "range_max = 1 # maximum of the interval on which we wish to approximate our function\n",
+ "X = np.linspace(range_min, range_max-range_min, n_grid) # Optimisation grid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6bc40cc9",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: write the differential equation's analytical solution (given above) in the form of a Python function\n",
+ "# that takes the variable x as input - we'll use this later to compare with our result"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "6a4c54ba",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Parameters of the quantum machine learning procedure\n",
+ "N = nphotons # Number of photons\n",
+ "m = nphotons # Number of modes\n",
+ "eta = 5 # weight granted to the initial condition\n",
+ "a = 200 # Approximate boundaries of the interval that the image of the trial function can cover\n",
+ "fock_dim = comb(N + m - 1, N)\n",
+ "# lambda coefficients for all the possible outputs\n",
+ "lambda_random = 2 * a * np.random.rand(fock_dim) - a\n",
+ "# dx serves for the numerical differentiation of f\n",
+ "dx = (range_max-range_min) / (n_grid - 1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "662ad59e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "|1,1,1,1>\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Input state with N photons and m modes\n",
+ "input_state = pcvl.BasicState([1]*N+[0]*(m-N))\n",
+ "print(input_state)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8b94a785",
+ "metadata": {},
+ "source": [
+ "## Definition of the circuit\n",
+ "\n",
+ "We will generate a Haar-random initial unitary using QR decomposition built in Perceval `Matrix.random_unitary`, the circuit is defined by the combination of 3 sub-circuits - the intermediate phase is a parameter."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "b90ce704",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\"Haar unitary parameters\"\n",
+ "# number of parameters used for the two universal interferometers (2*m**2 per interferometer)\n",
+ "parameters = np.random.normal(size=4*m**2)\n",
+ "\n",
+ "px = pcvl.P(\"px\")\n",
+ "\n",
+ "#TO DO: build the circuit we'll use - remember the order of computation - mathematically\n",
+ "# we write W2SW1 but physically we perform W1SW2\n",
+ "# HINT 1: remember that S is just a phase shift, you can give it the angle controlled by\n",
+ "# parameter px and apply it on mode 0\n",
+ "# HINT 2: use pcvl.Unitary(pcvl.Matrix.random_unitary()) to create W1 and W2\n",
+ "# the first varible inside the function will be the size of the matrix - think about\n",
+ "# what defines its size!\n",
+ "# the second variable are the parameters - you can choose them from the previously\n",
+ "# defined 'parameters' variable but be careful not to use the same parameters for both W1 and W2!\n",
+ "# add all the parts of the circuit in correct order of computation in variable 'c'\n",
+ "\n",
+ "backend = pcvl.BackendFactory().get_backend(\"SLOS\")\n",
+ "backend.set_circuit(pcvl.Unitary(pcvl.Matrix.random_unitary(m)))\n",
+ "backend.preprocess([input_state])\n",
+ "\n",
+ "pcvl.pdisplay(c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "79b7fef9",
+ "metadata": {},
+ "source": [
+ "### Expectation value and loss function computation\n",
+ "\n",
+ "The expectation value of the measurement operator $\\mathcal{M}(\\boldsymbol{\\lambda})$ is obtained directly from Fock state probabilities computed by Perceval. Given this expectation value, the code snippet below computes the loss function defined in the Introduction.\n",
+ "\n",
+ "Note the use of the `all_prob` simulator method giving directly access to the probabilities of all possible output states, including null probabilities (probabilities of observing the state with m modes and 0 photons as all photons were lost). This calculation is optimized in the SLOS backend."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "27aa9449",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def computation(params):\n",
+ " global current_loss\n",
+ " global computation_count\n",
+ " \"compute the loss function of a given differential equation in order for it to be optimized\"\n",
+ " computation_count += 1\n",
+ " f_theta_0 = 0 # boundary condition\n",
+ " coefs = lambda_random # coefficients of the M observable\n",
+ " # initial condition with the two universal interferometers and the phase shift in the middle\n",
+ " U_1 = pcvl.Matrix.random_unitary(m, params[:2 * m ** 2])\n",
+ " U_2 = pcvl.Matrix.random_unitary(m, params[2 * m ** 2:])\n",
+ "\n",
+ " px = pcvl.P(\"x\")\n",
+ " c = pcvl.Unitary(U_2) // (0, pcvl.PS(px)) // pcvl.Unitary(U_1)\n",
+ "\n",
+ " px.set_value(np.pi * x_0)\n",
+ " backend.set_circuit(c)\n",
+ " f_theta_0 = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " # boundary condition given a weight eta\n",
+ " loss = eta * (f_theta_0 - f_0) ** 2 * len(X)\n",
+ "\n",
+ " # Y[0] is before the domain we are interested in (used for differentiation), x_0 is at Y[1]\n",
+ " Y = np.zeros(n_grid + 2)\n",
+ "\n",
+ " # x_0 is at the beginning of the domain, already calculated\n",
+ " Y[1] = f_theta_0\n",
+ "\n",
+ " px.set_value(np.pi * (range_min - dx))\n",
+ " backend.set_circuit(c)\n",
+ " Y[0] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ "\n",
+ " for i in range(1, n_grid):\n",
+ " x = X[i]\n",
+ " px.set_value(np.pi * x)\n",
+ " backend.set_circuit(c)\n",
+ " Y[i + 1] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " px.set_value(np.pi * (range_max + dx))\n",
+ " backend.set_circuit(c)\n",
+ " Y[n_grid + 1] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " # Differentiation\n",
+ " Y_prime = (Y[2:] - Y[:-2])/(2*dx)\n",
+ "\n",
+ " loss += np.sum((F(Y_prime, Y[1:-1], X))**2)\n",
+ "\n",
+ " current_loss = loss / len(X)\n",
+ " return current_loss"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ff86ccf8",
+ "metadata": {},
+ "source": [
+ "### Classical optimisation\n",
+ "\n",
+ "Finally the code below performs the optimisation procedure using the loss function defined in the previous section. To this end, we use a Broyden–Fletcher–Goldfarb–Shanno (BFGS) optimiser \\[5\\] from the SciPy library. Since we're performing the optimization classically, this is considered a hybrid quantum-classical algorithm."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "51ca61eb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def callbackF(parameters):\n",
+ " \"\"\"callback function called by scipy.optimize.minimize allowing to monitor progress\"\"\"\n",
+ " global current_loss\n",
+ " global computation_count\n",
+ " global loss_evolution\n",
+ " global start_time\n",
+ " now = time.time()\n",
+ " pbar.set_description(\"M= %d Loss: %0.5f #computations: %d elapsed: %0.5f\" % \n",
+ " (m, current_loss, computation_count, now-start_time))\n",
+ " pbar.update(1)\n",
+ " loss_evolution.append((current_loss, now-start_time))\n",
+ " computation_count = 0\n",
+ " start_time = now"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "a8dd63fd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "M= 4 Loss: 0.02469 #computations: 325 elapsed: 4.56400: : 85it [01:47, 2.53s/it] "
+ ]
+ }
+ ],
+ "source": [
+ "computation_count = 0\n",
+ "current_loss = 0\n",
+ "start_time = time.time()\n",
+ "loss_evolution = []\n",
+ "\n",
+ "pbar = tqdm.tqdm()\n",
+ "res = minimize(computation, parameters, callback=callbackF, method='BFGS', options={'gtol': 1E-2})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57d69698",
+ "metadata": {},
+ "source": [
+ "After the optimisation procedure, the optimal unitary parameters (in `res.x`) can be used to determine the quantum circuit parameters (beam-splitter reflectivity and phase-shifter angles) for an experimental realisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "12b6343c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unitary parameters [ 1.33891468 0.18671167 0.23294109 0.66027105 -0.90538747 -0.16478482\n",
+ " -1.79778695 0.27640065 -0.42235108 -0.42638238 -0.55720517 -0.50342402\n",
+ " 2.98759829 0.58048485 -0.05092819 1.36887037 0.76989739 -0.45710592\n",
+ " 0.60972939 -1.30593682 0.31607202 0.80690103 -0.07061116 1.74802391\n",
+ " -0.33214799 -0.10327618 -0.09204192 0.08248837 0.44292407 1.5847011\n",
+ " -0.15747674 0.20716982 -0.39656236 -2.52802577 -0.13810356 1.15592549\n",
+ " -0.41093697 1.05903189 1.11363313 0.92263739 -0.85430684 0.86256034\n",
+ " 1.14379369 0.29563571 0.94241894 -1.00363776 -0.4509711 -1.69484381\n",
+ " -0.90294638 0.76882232 0.54888516 -1.35142993 -0.25475156 -0.6617475\n",
+ " -0.62901547 -0.35290343 -0.48896483 -1.07626614 -0.93944671 -0.10220152\n",
+ " -0.51258919 0.07453675 -0.15409034 0.22112889]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"Unitary parameters\", res.x)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b5fc2804",
+ "metadata": {},
+ "source": [
+ "### Plotting the approximation\n",
+ "\n",
+ "We can now plot the result of our optimisation in order to compare the QML algorithm's output and the analytical solution of the differential equation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "1e37ce40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_solution(m, N, X, optim_params, lambda_random):\n",
+ " Y = []\n",
+ " U_1 = pcvl.Matrix.random_unitary(m, optim_params[:2 * m ** 2])\n",
+ " U_2 = pcvl.Matrix.random_unitary(m, optim_params[2 * m ** 2:])\n",
+ " px = pcvl.P(\"x\")\n",
+ " c = pcvl.Unitary(U_2) // (0, pcvl.PS(px)) // pcvl.Unitary(U_1)\n",
+ "\n",
+ " for x in X:\n",
+ " px.set_value(np.pi * x)\n",
+ " backend.set_circuit(c)\n",
+ " f_theta = np.sum(np.multiply(backend.all_prob(input_state), lambda_random))\n",
+ " Y.append(f_theta)\n",
+ " exact = u(X)\n",
+ " plt.plot(X, Y, label=\"Approximation with {} photons\".format(N))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "28a1d993",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGdCAYAAAAfTAk2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy88F64QAAAACXBIWXMAAA9hAAAPYQGoP6dpAACAm0lEQVR4nO3dd1xV9R/H8dflsgQBRRRQETfi3oojLQ211Iaz3Kn9zFyZlba0aVamZlppalbmyr33Fjc4cQ8wQUTZyrzf3x8nb6GooFwO4/N8PO4jOOd7zn2fI3E/nPM9369BKaUQQgghhMhHrPQOIIQQQgiR3aTAEUIIIUS+IwWOEEIIIfIdKXCEEEIIke9IgSOEEEKIfEcKHCGEEELkO1LgCCGEECLfkQJHCCGEEPmOtd4B9GAymbh27RpOTk4YDAa94wghhBAiE5RSxMXFUbJkSaysHn6NpkAWONeuXcPLy0vvGEIIIYR4DKGhoZQuXfqhbQpkgePk5ARoJ8jZ2VnnNEIIIYTIjNjYWLy8vMyf4w9TIAucu7elnJ2dpcARQggh8pjMdC+RTsZCCCGEyHekwBFCCCFEviMFjhBCCCHynQLZB0cIkXsppUhNTSUtLU3vKEIIHdjY2GA0Gp94P1LgCCFyjeTkZMLCwrh9+7beUYQQOjEYDJQuXZrChQs/0X6kwBFC5Aomk4lLly5hNBopWbIktra2MhCnEAWMUoobN25w9epVKlWq9ERXcqTAEULkCsnJyZhMJry8vHBwcNA7jhBCJ8WLF+fy5cukpKQ8UYEjnYyFELnKo4ZfF0Lkb9l15VZ+kwghhBAi35ECRwghBH379uXFF1/U5b0vX76MwWAgKChIl/fPyPbt2zEYDERHRz+0XdmyZZk8eXKOZHoUPf8NcyMpcIQQIpvs3bsXo9FI27Zt9Y6SZVOmTOHXX3+1+Ptk9CHs5eVFWFgY1atXt/j7Z1aTJk0ICwvDxcUFgF9//ZUiRYpk+/uMHz8eg8HAiBEjsn3fj8NSx6kHixY4O3fupEOHDpQsWRKDwcDy5csfuc2OHTuoV68e9vb2lC9fnp9++um+NkuWLKFq1arY2dlRtWpVli1bZoH0QgiRNbNnz2bo0KHs3r2bkJCQHHnPlJSUbNmPi4uLbh9sRqMRDw8PrK1zz3Mvtra2eHh4WPRJvoMHDzJjxgxq1qxpsfcoyCxa4CQkJFCrVi1++OGHTLW/dOkSzz33HM2bNycwMJD333+fYcOGsWTJEnObgIAAunXrRq9evTh69Ci9evWia9eu7N+/31KHkWlKKd6cd4T5B0JITJFByoQoSBISEli0aBFvvPEG7du3v+9qyN1bHmvWrKFWrVrY29vTqFEjjh8/bm5z96/n5cuXU7lyZezt7Xn22WcJDQ01txk3bhy1a9dm9uzZlC9fHjs7O5RShISE8MILL1C4cGGcnZ3p2rUr169fB+D06dM4ODjw559/mvezdOlS7O3tze9/75WVli1bMnToUEaMGEHRokVxd3dnxowZJCQk0K9fP5ycnKhQoQLr1q0zb5OWlkb//v0pV64chQoVwsfHhylTpqTLPnfuXFasWIHBYMBgMLB9+/YMb1Ht2LGDhg0bYmdnh6enJ6NHjyY1NTVdvmHDhvHuu+/i6uqKh4cH48aNe+C/z/Hjx7GysiIyMhKAqKgorKys6NKli7nN+PHj8fPzS/fvFR0dzfbt2+nXrx8xMTHm3P99r9u3b/Paa6/h5OREmTJlmDFjxgNz3BUfH0+PHj2YOXMmRYsWfWT7u//uP//8s/lJwy5dumR4C+3bb7/F09OTYsWK8eabb6YrgqOioujduzdFixbFwcGBdu3ace7cOfMxP+g4H7Yd/Puzu2HDBnx9fSlcuDBt27YlLCzM3Gb79u00bNgQR0dHihQpQtOmTbly5cojj/2xqRwCqGXLlj20zbvvvquqVKmSbtn//vc/1bhxY/P3Xbt2VW3btk3Xpk2bNqp79+6ZzhITE6MAFRMTk+ltMmP3uRuqZ9dPVdURi1TdTzeqKZvPqoSklGx9DyHyqzt37qhTp06pO3fumJeZTCaVkJSS4y+TyZTl/LNmzVL169dXSim1atUqVbZs2XT72bZtmwKUr6+v2rhxozp27Jhq3769Klu2rEpOTlZKKTVnzhxlY2Oj6tevr/bu3asOHTqkGjZsqJo0aWLez9ixY5Wjo6Nq06aNOnLkiDp69KgymUyqTp06qlmzZurQoUNq3759qm7duqpFixbm7aZNm6ZcXFzU5cuX1d9//61cXV3VpEmTzOv79OmjXnjhBfP3LVq0UE5OTuqzzz5TZ8+eVZ999pmysrJS7dq1UzNmzFBnz55Vb7zxhipWrJhKSEhQSimVnJysPv74Y3XgwAF18eJF9ccffygHBwe1cOFCpZRScXFx5t/hYWFhKiwsTCUlJalLly4pQAUGBiqllLp69apycHBQgwcPVsHBwWrZsmXKzc1NjR07Nl0+Z2dnNW7cOHX27Fk1d+5cZTAY1MaNGzP89zGZTMrNzU399ddfSimlli9frtzc3FSJEiXMbfz9/dV7772X7t8rKipKJSUlqcmTJytnZ2dz7ri4OKWUUt7e3srV1VVNmzZNnTt3To0fP15ZWVmp4ODgh/689O7dW40YMcJ8LMOHD39o+7v/7s8884wKDAxUO3bsUBUrVlSvvvpqun9DZ2dnNWjQIBUcHKxWrVqlHBwc1IwZM8xtOnbsqHx9fdXOnTtVUFCQatOmjapYsaJKTk5+6HE+bDul/v3Zbd26tTp48KA6fPiw8vX1NedLSUlRLi4uatSoUer8+fPq1KlT6tdff1VXrly571gz+l1wV1Y+v3NVgdO8eXM1bNiwdMuWLl2qrK2tzSfRy8tLfffdd+nafPfdd6pMmTIP3G9iYqKKiYkxv0JDQy1S4MRdvKLSjNYq3s5B/VbnOfXsaz+oxl9uVssDrz7WL0whCpKMfqklJKUo7/dW5/jrcf4wadKkiZo8ebJSSvtl7ubmpjZt2mRef/cDc8GCBeZlN2/eVIUKFTIXAHPmzFGA2rdvn7lNcHCwAtT+/fuVUtoHnY2NjYqIiDC32bhxozIajSokJMS87OTJkwpQBw4cMC97/vnnVfPmzVWrVq3Us88+m+73UkYFTrNmzczfp6amKkdHR9WrVy/zsrCwMAWogICAB56XwYMHq06dOj3wfZRS9xU477//vvLx8UmXb9q0aapw4cIqLS0tw3xKKdWgQQNzgZKRl19+WQ0ZMkQppdSIESPU22+/rdzc3NTJkydVSkqKKly4sFq3bp1SKn2Bo5T2b+Pi4nLfPr29vVXPnj3N35tMJlWiRAn1448/PjDH/PnzVfXq1c0/65ktcIxGowoNDTUvW7dunbKyslJhYWFKKe3cent7q9TUVHObLl26qG7duimllDp79qwC1J49e8zrIyMjVaFChdSiRYseeJyZ3Q5Q58+fN7eZNm2acnd3V0ppP+uA2r59+0OPU6nsK3ByVSfj8PBw3N3d0y1zd3cnNTXVfFnxQW3Cw8MfuN/x48fj4uJifnl5eWV/eKBwRBhWFcrjmHSbXoFr2Th7CO/98Rnf/LSegb8d4lZCskXeVwihrzNnznDgwAG6d+8OgLW1Nd26dWP27Nn3tb17CwTA1dUVHx8fgoODzcusra2pX7+++fsqVapQpEiRdG28vb0pXry4+fvg4GC8vLzS/W6rWrXqfdvNnj2bY8eOceTIEX799ddH9i/5b98Qo9FIsWLFqFGjhnnZ3d/FERER5mU//fQT9evXp3jx4hQuXJiZM2dmuT9ScHAwfn5+6fI1bdqU+Ph4rl69mmE+AE9Pz3RZ7tWyZUu2b98OaLfAnn76aZ566il27NjBwYMHuXPnDk2bNs1S1ntzGAwGPDw8HpgjNDSU4cOH88cff2Bvb5+l9ylTpgylS5c2f+/n54fJZOLMmTPmZdWqVUs3ON5/z0lwcDDW1tY0atTIvL5YsWL3/QzeK7PbOTg4UKFChQzf29XVlb59+9KmTRs6dOjAlClT0t2+soTc06PrH/f+D6eUum95Rm0e9j/qmDFjGDlypPn72NhYyxQ5jRrB6dOwdStMmwbLlvHiqR08d2YPU069wvNXevBdj/r4VSiW/e8tRD5UyMbIqU/b6PK+WTFr1ixSU1MpVaqUeZlSChsbG6Kioh7Zx+Le318Z/T777zJHR8d06x70O/De5UePHiUhIQErKyvCw8MpWbLkQ3PZ2Njcl+G/y+7u22QyAbBo0SLeeustJk6ciJ+fH05OTnzzzTdZ7iOZ0fFk9FmQUb67WTLSsmVLhg8fzvnz5zlx4gTNmzfnwoUL7Nixg+joaOrVq4eTk1OWsmY1x+HDh4mIiKBevXrmZWlpaezcuZMffviBpKSkTI/ee/dcZPac3D2H93rUZ2hmt8vovf+77Zw5cxg2bBjr169n4cKFfPjhh2zatInGjRs/8L2fRK66guPh4XHflZiIiAisra0pVqzYQ9vce1Xnv+zs7HB2dk73shiDAVq1gqVL4fBhaN0a27RU3tn1Oz/+NJSPv17CggM583SFEHmdwWDAwdY6x19ZeXImNTWV3377jYkTJxIUFGR+HT16FG9vb+bNm5eu/b59+8xfR0VFcfbsWapUqZJuf4cOHTJ/f+bMGaKjo9O1uVfVqlUJCQlJ1xn51KlTxMTE4OvrC8CtW7fo27cvH3zwAf369aNHjx7cuXMn08eZGbt27aJJkyYMHjyYOnXqULFiRS5cuJCuja2t7SNniq9atSp79+5N9+G4d+9enJyc0hWRWVW9enWKFSvG559/Tq1atXB2dqZFixbs2LGD7du306JFiwdum5ncmdGqVSuOHz+e7melfv369OjRg6CgoIcWNyEhIVy7ds38fUBAAFZWVlSuXDlT7121alVSU1PTFZw3b97k7Nmz5p+TjI4zM9tlVp06dRgzZgx79+6levXq6Tq+Z7dcVeD4+fmxadOmdMs2btxI/fr1zZXhg9o0adIkx3JmWt26sHEj/PEHqkgRaoedY+mvI9g84RfGrwt+YFUshMg7Vq9eTVRUFP3796d69erpXp07d2bWrFnp2n/66ads2bKFEydO0LdvX9zc3NI9vWRjY8PQoUPZv38/R44coV+/fjRu3JiGDRs+MEPr1q2pWbMmPXr04MiRIxw4cIDevXvTokUL8+2uQYMG4eXlxYcffsh3332HUopRo0Zl67moWLEihw4dYsOGDZw9e5aPPvqIgwcPpmtTtmxZjh07xpkzZ4iMjMzwMffBgwcTGhrK0KFDOX36NCtWrGDs2LGMHDnyiabyMBgMPPXUU/zxxx+0bNkS0G4vJScns2XLFvOyjJQtW5b4+Hi2bNlCZGTkY8947+TkdN/PiaOjI8WKFXvkOED29vb06dOHo0ePsmvXLoYNG0bXrl3x8PDI1HtXqlSJF154gYEDB7J7926OHj1Kz549KVWqFC+88MIDjzMz2z3KpUuXGDNmDAEBAVy5coWNGzc+VoGUFRYtcOLj480VKmgHGBQUZL4fO2bMGHr37m1uP2jQIK5cucLIkSMJDg5m9uzZzJo1K93/hMOHD2fjxo1MmDCB06dPM2HCBDZv3pxrBkm6j8EAPXpgOHEC9dRTOCXf4Zeln2E9fjwfLz+BySRFjhB52axZs2jdurV5QLj/6tSpE0FBQRw5csS87KuvvmL48OHUq1ePsLAwVq5cia2trXm9g4MD7733Hq+++ip+fn4UKlSIBQsWPDTD3XHGihYtylNPPUXr1q0pX748CxcuBOC3335j7dq1/P7771hbW+Pg4MC8efP45ZdfWLt2bTadCe13+Msvv0y3bt1o1KgRN2/eZPDgwenaDBw4EB8fH3M/nT179ty3n1KlSrF27VoOHDhArVq1GDRoEP379+fDDz984oxPP/00aWlp5mLGYDDQvHlzAJo1a/bA7Zo0acKgQYPo1q0bxYsX5+uvv37iLFlVsWJFXn75ZZ577jn8/f2pXr0606dPz9I+5syZQ7169Wjfvj1+fn4opVi7dq35IsKDjvNR2z2Kg4MDp0+fplOnTlSuXJnXX3+dIUOG8L///S9rJyErHtkN+Qnc7YV+76tPnz5KKa3H938fY1RKqe3bt6s6deooW1tbVbZs2Qx7oi9evFj5+PgoGxsbVaVKFbVkyZIs5bLUY+KPlJys1JtvKgVKgZpdr4MaszhQpaXJE1ZCPOzJifzg3qdyMvKgJ3WEGDt2rKpVq5beMXJEdj1FZdFOxi1btnzobZiMhgVv0aJFur92MtK5c2c6d+78pPFyno0N/PAD+PrCkCH0O7yKJePi+dJmMh90rGHRETOFEEKIgiRX9cEpMN58E/74A5PRSKeT2/D58G1mbD+vdyohhBAi3zCoh11iyadiY2NxcXEhJibGsk9UPcqyZZi6dMEqLY059TrgOnM6L9Qp/ejthMiHEhMTuXTpEuXKlcvy+CBCiPzjYb8LsvL5LVdw9PTSS1jNmQNAv8OruPjWBxy7Gq1vJiGEECIfkAJHb716YZo6FYC3dvzGwncmEhGXqHMoIYQQIm+TAicXsBoyhKShwwH46K+vmfTFH6SmPXg0TiGEEEI8nBQ4uYTdpIkkPNsG+9Rkhk97jxl/7Xv0RkIIIYTIkBQ4uYXRiOOSxcSVq4hH/C1qvjeY3aev651KCCGEyJOkwMlNnJxwWrWcZDt7ml05yulBb8sM5EIIIcRjkAInt6lWDWbMBOC1HX8y98s5MmeVEMKsbNmyTJ48+Yn2sX37dgwGA9HR0dmS6fLlyxgMBvO0PNktu/JaOqfIXaTAyYVse/fkVvdeWKHoNvVD1u8O1juSECIT9u7di9FopG3btnpHMWvZsuV9c/U1adKEsLCwDOfPyi/69u2bbhJTAC8vL8LCwh45qaXIH6TAyaVcZ04nuqQ3JeMiUYPfJCJWHh0XIrebPXs2Q4cOZffu3eZJhXMjW1tbPDw8Ctz0MEajEQ8PD6ytLTpLkcglpMDJrQoXpvDi+aRZGXnuxHZWfTBZ70RCiIdISEhg0aJFvPHGG7Rv3/6+ufbu3mbZsmUL9evXx8HBgSZNmnDmzBlzmwsXLvDCCy/g7u5O4cKFadCgAZs3b37ge7722mu0b98+3bLU1FQ8PDyYPXs2ffv2ZceOHUyZMgWDwYDBYODy5csZ3vLZs2cPLVq0wMHBgaJFi9KmTRuioqIAWL9+Pc2aNaNIkSIUK1aM9u3bc+HChSydn+nTp1OpUiXs7e1xd3dPN59gUlISw4YNo0SJEtjb29OsWTMOHjz4wH2NGzeO2rVrp1s2efJkypYta14/d+5cVqxYYT7u7du3Z3iLaseOHTRs2BA7Ozs8PT0ZPXo0qamp5vUtW7Zk2LBhvPvuu7i6uuLh4cG4ceOydOxCH1Lg5GLWTfy4NXwUAC/M/oode07pnEiIHKYUJCTk/Osx+r0tXLgQHx8ffHx86NmzJ3PmZNx/7oMPPmDixIkcOnQIa2trXnvtNfO6+Ph4nnvuOTZv3kxgYCBt2rShQ4cOD7waNGDAANavX09YWJh52dq1a4mPj6dr165MmTIFPz8/Bg4cSFhYGGFhYXh5ed23n6CgIFq1akW1atUICAhg9+7ddOjQgbS0NEAr3kaOHMnBgwfZsmULVlZWvPTSS5hMmRuv69ChQwwbNoxPP/2UM2fOsH79ep566inz+nfffZclS5Ywd+5cjhw5QsWKFWnTpg23bt3K1P7vNWrUKLp27Urbtm3Nx92kSZP72v39998899xzNGjQgKNHj/Ljjz8ya9YsPv/883Tt5s6di6OjI/v37+frr7/m008/ZdOmTY+VTeSgbJ7lPE/IynTruktKUte9KykFan2tZ1RcYoreiYSwiDt37qhTp06pO3fu/LswPl4prdzI2Vd8fJbzN2nSRE2ePFkppVRKSopyc3NTmzZtMq/ftm2bAtTmzZvNy9asWaOA9Md8j6pVq6qpU6eav/f29laTJk1Kt37ChAnm71988UXVt29f8/ctWrRQw4cPT7fPu1mioqKUUkq98sorqmnTppk+1oiICAWo48ePK6WUunTpkgJUYGBghu2XLFminJ2dVWxs7H3r4uPjlY2NjZo3b555WXJysipZsqT6+uuvM8w7duxYVatWrXT7mTRpkvL29jZ/36dPH/XCCy+ka3Nvzvfff1/5+Pgok8lkbjNt2jRVuHBhlZaWppTSzl+zZs3S7adBgwbqvffey/BYxZPL8HfBP7Ly+S1XcHI7W1uc//yNNIMVbY5uZfUXM/ROJIS4x5kzZzhw4ADdu3cHwNramm7dujF79uz72tasWdP8taenJwARERGAdqXk3XffpWrVqhQpUoTChQtz+vTph/bnGTBgAHP+mdMuIiKCNWvWpLsqlBl3r+A8yIULF3j11VcpX748zs7OlCtXDiDT/YyeffZZvL29KV++PL169WLevHncvn3bvO+UlBSaNm1qbm9jY0PDhg0JDrbsAxbBwcH4+fml64vUtGlT4uPjuXr1qnnZf//NQPt3u/tvJnIv6WmVB9g3aUxov0F4zZ5Os+8/4Vy/TlQq5653LCEsz8EB4uP1ed8smDVrFqmpqZQqVcq8TCmFjY0NUVFRFC1a1LzcxsbG/PXdD9a7t3reeecdNmzYwLfffkvFihUpVKgQnTt3Jjn5weNh9e7dm9GjRxMQEEBAQABly5alefPmWcpfqFChh67v0KEDXl5ezJw5k5IlS2IymahevfpDc/2Xk5MTR44cYfv27WzcuJGPP/6YcePGcfDgQfNtvHs7PCulHtgJ2srK6r7bfykpKZnK8qj3yCjPf//N7q7L7O05oR+5gpNHeH3/NTeLeVA6JoKTb74nY+OIgsFgAEfHnH9l4emi1NRUfvvtNyZOnEhQUJD5dfToUby9vZk3b16m97Vr1y769u3LSy+9RI0aNfDw8ODy5csP3aZYsWK8+OKLzJkzhzlz5tCvX790621tbc19aR6kZs2abNmyJcN1N2/eJDg4mA8//JBWrVrh6+tr7nycFdbW1rRu3Zqvv/6aY8eOcfnyZbZu3UrFihWxtbVl9+7d5rYpKSkcOnQIX1/fDPdVvHhxwsPD0/0evHdsm8wcd9WqVdm7d2+6/ezduxcnJ6d0xarIm6TAySscHTFNmgLAcxvmsXPVLp0DCSEAVq9eTVRUFP3796d69erpXp07d2bWrFmZ3lfFihVZunSpuUB69dVXM3WlYMCAAcydO5fg4GD69OmTbl3ZsmXZv38/ly9fJjIyMsP9jRkzhoMHDzJ48GCOHTvG6dOn+fHHH4mMjKRo0aIUK1aMGTNmcP78ebZu3crIkSMzfUygnaPvv/+eoKAgrly5wm+//YbJZMLHxwdHR0feeOMN3nnnHdavX8+pU6cYOHAgt2/fpn///hnur2XLlty4cYOvv/6aCxcuMG3aNNatW3ffcR87dowzZ84QGRmZ4RWewYMHExoaytChQzl9+jQrVqxg7NixjBw5Eisr+XjM6+RfMA8p3rMLFxq1xNaUisPIt0hMTn30RkIIi5o1axatW7fOcNC8Tp06ERQUxJEjRzK1r0mTJlG0aFGaNGlChw4daNOmDXXr1n3kdq1bt8bT05M2bdpQsmTJdOtGjRqF0WikatWqFC9ePMN+M5UrV2bjxo0cPXqUhg0b4ufnx4oVK7C2tsbKyooFCxZw+PBhqlevzltvvcU333yTqeO5q0iRIixdupRnnnkGX19ffvrpJ+bPn0+1atUA+Oqrr+jUqRO9evWibt26nD9/ng0bNqS7tfdfvr6+TJ8+nWnTplGrVi0OHDjAqFGj0rUZOHAgPj4+1K9fn+LFi7Nnz5779lOqVCnWrl3LgQMHqFWrFoMGDaJ///58+OGHWTo+kTsZVAG81xEbG4uLiwsxMTE4OzvrHSdLEs+cx1C9KnapKaz/4ifavv8/vSMJkS0SExO5dOkS5cqVw97eXu84ecrt27cpWbIks2fP5uWXX9Y7jhBP5GG/C7Ly+S1XcPIYe5+KXOylFTW+Ez/l1q04nRMJIfRiMpm4du0aH330ES4uLnTs2FHvSELkGlLg5EGVJ33BLWdXvG9d4+CoT/WOI4TQSUhICKVKlWLRokXMnj1bpiAQ4j+kwMmDjC7O3BwzFoAmf04n9OwVnRMJIfRQtmxZlFKEhoY+dBwbIQoiKXDyqErvDuGKV2Wckm5zftTHescRQgghchUpcPIqKytS/5kvxW/dAi4fO6tzICGEECL3kAInD6vQqzNnK9fCPjWZqyPf1zuOENmiAD7YKYT4j+z6HSAFTl5mMGDz1XgAGm1bzsWAIH3zCPEE7g6Hf3eOIiFEwXR3ChCj0fhE+5Eu93lcuZfacaJmE6of20vk22Mov3fdozcSIhcyGo0UKVLEPImhg4PDA+ciEkLkTyaTiRs3buDg4PDETwVKgZMPOE2cAM82p37ABs5v3kPF1k0fvZEQuZCHhweAzNQsRAFmZWVFmTJlnvgPHClw8gHv1s040vhZ6u7bRMKo0RAk81SJvMlgMODp6UmJEiUea3ZoIUTeZ2trmy1zgUmBk0+4TZpAapMt1Dq6m7PLNlD5pTZ6RxLisRmNxie+/y6EKNikk3E+UaZxHQ49/QIAKR/KuDhCCCEKNilw8pFS335BipWRaqcOcHndNr3jCCGEELqRAicf8arjy+Gm7QCI+1jmqBJCCFFwSYGTz7h++jEmDNQ4tJ3wPQf1jiOEEELoQgqcfKZyywYcrPc0ABEffKJzGiGEEEIfUuDkQ7YfatM2VNu5jujjwTqnEUIIIXJejhQ406dPp1y5ctjb21OvXj127XrwOC19+/bFYDDc96pWrZq5za+//pphm8TExJw4nFyv9gvPcMi3EUZlImS0XMURQghR8Fi8wFm4cCEjRozggw8+IDAwkObNm9OuXTtCQkIybD9lyhTCwsLMr9DQUFxdXenSpUu6ds7OzunahYWFYW9vb+nDyRMMBgPJ744GoMqGpdy5dEXnREIIIUTOsniB891339G/f38GDBiAr68vkydPxsvLix9//DHD9i4uLnh4eJhfhw4dIioqin79+qVrZzAY0rW7O8S70DTq/QJHy9XANi2FC6PliSohhBAFi0ULnOTkZA4fPoy/v3+65f7+/uzduzdT+5g1axatW7fG29s73fL4+Hi8vb0pXbo07du3JzAw8IH7SEpKIjY2Nt0rvzNaGbg57G0AKiz7k+TrN3ROJIQQQuQcixY4kZGRpKWl4e7unm65u7s74eHhj9w+LCyMdevWMWDAgHTLq1Spwq+//srKlSuZP38+9vb2NG3alHPnzmW4n/Hjx+Pi4mJ+eXl5Pf5B5SFNBvfgtGdFCqUkcv7ziXrHEUIIIXJMjnQyvndGUKVUpmYJ/fXXXylSpAgvvvhiuuWNGzemZ8+e1KpVi+bNm7No0SIqV67M1KlTM9zPmDFjiImJMb9CQ0Mf+1jyEntba670eh0Aj99+geRknRMJIYQQOcOiBY6bmxtGo/G+qzURERH3XdW5l1KK2bNn06tXL2xtbR/a1srKigYNGjzwCo6dnR3Ozs7pXgVF3XcHcb2wK66xN7k8fY7ecYQQQogcYdECx9bWlnr16rFp06Z0yzdt2kSTJk0euu2OHTs4f/48/fv3f+T7KKUICgrC09PzifLmR8WLOXH4+VcAMH4/GZTSN5AQQgiRAyx+i2rkyJH88ssvzJ49m+DgYN566y1CQkIYNGgQoN0+6t27933bzZo1i0aNGlG9evX71n3yySds2LCBixcvEhQURP/+/QkKCjLvU6RX9v2RJFrb4nXpNLfWb9E7jhBCCGFx1pZ+g27dunHz5k0+/fRTwsLCqF69OmvXrjU/FRUWFnbfmDgxMTEsWbKEKVOmZLjP6OhoXn/9dcLDw3FxcaFOnTrs3LmThg0bWvpw8qSqNcuzsXE7/Hev4NbnE3Bt11rvSEIIIYRFGZQqePcsYmNjcXFxISYmpsD0x9mxfCctXmqByWAg5dRp7KpU1juSEEIIkSVZ+fyWuagKiKYdmhFQuQFWShHyyQS94wghhBAWJQVOAWFttCJywBsAlFo2HxUdrW8gIYQQwoKkwClAmr3xKmeLe+OQdIfQbzIeM0gIIYTID6TAKUCKFrbjeKe+ADjM/BlMJn0DCSGEEBYiBU4BU23UIGLsHHG78TfRy1bpHUcIIYSwCClwCpgqFTzY2eR5AKK+zfgxfCGEECKvkwKnALJ9czAA3vu3k3bxks5phBBCiOwnBU4B1KJjM/aVq42VUlydMFnvOEIIIUS2kwKnALK3MRLavS8ARef/DklJ+gYSQgghspkUOAVUnSF9CC/sinNcFFG/zdc7jhBCCJGtpMApoCqWLMLOp18GIOH7H3ROI4QQQmQvKXAKsCJD3yDVYEXpE4dJDTqqdxwhhBAi20iBU4C1fLo226s2BeDaV5N0TiOEEEJkHylwCjBbaysievYHoPjyxRAbq3MiIYQQIntIgVPANRvQmfOupSmUdJubv/ymdxwhhBAiW0iBU8CVcXNkf2uts3HyzzN0TiOEEEJkDylwBMXfGECylTWeZ4+TFhikdxwhhBDiiUmBI2jRrCrbff0ACPtOHhkXQgiR90mBI7CzNnK9S08AXJcugjt3dE4khBBCPBlrvQOI3KFe/65c/e4jSsdGEL9gMYX79dY7khBCZOhmfBKHr0RxLiKe8xHx3IhLIvpOMokpJqytDNjZGHF3ssPTxZ5K7k7UKOVCFU8n7KyNekcXOUgKHAFA1dJFmNe0PT3WzSb2h5+kwBFC5BpKKU5ei2X1sTC2nr7O2evxWd6Hg62RJhXcaOVbgueqe+LiYGOBpCI3MSillN4hclpsbCwuLi7ExMTg7Oysd5xcY8nyvbz0UjOsUKizZzFUqqR3JCFEAZaQlMrSI1f5LeAK5yLSFzWV3QtTraQLFUsUxtPFnqIOttjZWJFmUtxOTiMiNpGr0XcIDovj+NVoom6nmLe1tbbCv6o7/ZqWpZ63a04flngCWfn8lgJHChyzmNspBNVsQosLh7g+eATu02R0YyFEzotPSmXO7kvM3HWR2MRUAOxtrHimSgnaVfekaUU3XB1tM70/k0lxKiyW7WciWHU0jDPX48zr6nsXZXjrSjSvVDzbj0NkPylwHkEKnAebNfJb+k96h7gibjhFXAMbuYwrhMgZaSbFn/uv8N2ms+YrLuXcHOnj502neqVxsn/y30d3b3f9FnCZZYF/k5KmfQQ2r+TG+8/54uspnwm5mRQ4jyAFzoPtPXWNSg2qUfx2NEmLl2LX+SW9IwkhCoCg0Gg+WHack9e0KWPKuzky4tnKtK/hiZWVwSLveT02kZ92XOCPfVdISVMYrQwMaFaOEa0rU8hWOiTnRlLgPIIUOA9mMinmP92dHjsXEda8NZ47N+kdSQiRjyWnmvh+yzmmbz+PSYGzvTWj2vjwasMyWBtzZiSTkJu3+Wp9MGuPhwPg5VqISV1rU7+s9M/JbbLy+S3j4Ih0rKwMpPZ9DYASe7bB9es6JxJC5FdXbibw0vQ9/LBNK25eqF2SraNa0tuvbI4VNwBlijkwvUc9ZvWpT0kXe0Jv3aHrzwFM3nyW1DRTjuUQ2UsKHHGf1i89xZGSPhhNaUTPnKN3HCFEPrTxZDjtp+7m5LVYijrYML1HXaZ0r4NbYTvdMrXydWfDW0/xct1SmBRM3nyOPnMOEJWQrFsm8fikwBH3KVWkEIEtOwKQOvtXKHh3MYUQFqKUYsrmc7z++2HiElOp512UtcOb81wNT72jAeBkb8N3XWszpXttHGyN7Dl/kw4/7ObktRi9o4kskgJHZKhY/14kGW1wu3QGFRiodxwhRD6QlJrGyEVHmbT5LAD9mpZlweuN8XQppHOy+71QuxTLBjfFu5gDV6Pu0PWnAHacvaF3LJEFUuCIDLVu6stWH20Czhs//KxzGiFEXheflErf2QdZFvg3RisDX75Ug7EdqmGTg31tssrHw4mVbzajacViJCSn8dqvB1l0MFTvWCKTcu9PltBVYTtrQjp0AcDxr0WQLPeghRCPJyohmR4z9xFw8SaOtkZ+7deAVxuV0TtWprg42DCnb0NerlOKNJPi3SXHmLX7kt6xRCZIgSMeqFqfzlwv7IpjXDQpq1brHUcIkQfdjE+i+4x9HL0aQ1EHG+a/3jjPjRpsa23FxK61+F+L8gB8tvoUP2w9p3Mq8Sgy2aZ4ID8fd+bXaU3PXYu4OW0GHp1e1juSECIPuZWQTI9f9nPmehzuznbMG9CIiiWcHm9nkZFw4gScPQvXrmlDWCQmaleXbW3ByQmKFYOyZaF8eahZE1xcsu1YDAYDo9tWwcHGmkmbz/LtxrMoBUNbyZx9uZUUOOKBjFYGknr0hF2LcNu5GW7cgOJ56y8vIYQ+Ym6n0OOX/ZwOj6OEkx3zBzamfPHCmd/BzZuwejVs3Qrbt0NISNZDVKoEzZvDs8+Cvz+4PtnAfQaDgeGtK2FnY8VX604zcdNZ7G2MDHyq/BPtV1iGjGQsIxk/1PmIOBJq1aNW+DniJ3xL4Xff1juSECKXu5OcRs9Z+zl8JQq3wnYseL0xFUtkorhJTIQlS2DuXK2wSUtLv758efD1hdKlwd0dHB21+fKSkiAuTruqc+WKdpXn3oLI2lordF59FTp1gkJP9uTW1C3nmLhJexrsi5eq06OR9xPtT2SOTNXwCFLgZM3PXUfyv8WTiKxUDbezJ/SOI4TIxVLSTAz87RDbz9zA2d6ahf/ze/QEltevw+TJMGMG3Lr17/JateC55+Dpp6FxY+02VGbdvAkHDsCWLbBhg3Z76y5XV+jbF4YPhzKP39n5mw2nmbbtAlYGmNm7Pq183R97XyJzct1UDdOnT6dcuXLY29tTr149du3a9cC227dvx2Aw3Pc6ffp0unZLliyhatWq2NnZUbVqVZYtW2bpwyiwirzWi2Qra9zOnYRjx/SOI4TIpZRSfLziBNvP3MDexorZfRs8vLi5cQNGjND6zXz1lVbceHnBJ5/A+fMQFARffqldeclKcQNaf5x27eDbb+H4cTh9Wttv2bLa+3z3HVSoAK+9BhcuPNbxjvL3oWv90pgUDPkzkONXZTDA3MTiBc7ChQsZMWIEH3zwAYGBgTRv3px27doR8oj7qWfOnCEsLMz8qlTp345cAQEBdOvWjV69enH06FF69epF165d2b9/v6UPp0Dyb16NbZUaAnDz51k6pxFC5FZz9lxm/oFQDAb44ZW6D56sMikJJkyAihVhyhTt1lTDhrBsGVy6BB9/rBUf2cnHR9vv+fNa355nnoHUVJgzB6pUgWHDtIIrCwwGA1+8VIPmldy4k5LGa3MPcjXqdvbmFo9PWVjDhg3VoEGD0i2rUqWKGj16dIbtt23bpgAVFRX1wH127dpVtW3bNt2yNm3aqO7du2cqU0xMjAJUTExMptoLpaYN/VopUDHF3JVKTdU7jhAil9l6+roqN3q18n5vtZq588KDG+7cqVSVKkppk8AoVbu2Uhs3KmUy5VzYuwIClGrb9t8sRYooNX16ln/Hxd5JVm0m7VDe761WrSZuV9EJyRYKLLLy+W3RKzjJyckcPnwYf3//dMv9/f3Zu3fvQ7etU6cOnp6etGrVim3btqVbFxAQcN8+27Rp88B9JiUlERsbm+4lsqZ8ny7E2DnifPM6pu079I4jhMhFzl6PY+ifgZgUdKvvRf9m5e5vdPs2DB0KTz2l3S4qUULrTHz4sHYLymDI+eCNG8O6dbB5M9SuDdHRMHgwNGkCJ09mejdO9jbM6dcAD2d7zkfE878/DpEis5DrzqIFTmRkJGlpabi7p+945e7uTnh4eIbbeHp6MmPGDJYsWcLSpUvx8fGhVatW7Ny509wmPDw8S/scP348Li4u5peXl9cTHlnB07KmF5uqPQVA5M+zdU4jhMgtbiUk03/uQeKTUmlYzpXPXqyO4d5iJTAQ6teHH37Qvh84UCtyevcGq1ww3myrVnDoEEydCs7OWufkunXh66/vf5LrATxdCjGnXwMK21mz7+Itxq89/eiNhEXlyE/WvT/sSqn7/wf4h4+PDwMHDqRu3br4+fkxffp0nn/+eb799tvH3ueYMWOIiYkxv0JDZS6RrLK3MXKjYycAnNes0O6ZCyEKtNQ0E2/8cZjQW3fwci3ETz3rYWt9z8fKL7+Anx8EB4Onp/ZE04wZULSoPqEfxGiEIUO0nO3bawMIvvcetG6tDSyYCb6ezkzqVhuA2XsusfJo5rYTlmHRAsfNzQ2j0XjflZWIiIj7rsA8TOPGjTl37t9hsT08PLK0Tzs7O5ydndO9RNbVfKUDfzsVx/52PCkrV+kdRwihs0mbz7L/0i0K21kzu08DXB1t/12ZnKxdqRk4UOtU3L699hTmPd0Lcp2SJWHlSpg9GwoX1gYZrFUL1q/P1ObPVnXnzae1DtKjlxzj7PU4C4YVD2PRAsfW1pZ69eqxadOmdMs3bdpEkyZNMr2fwMBAPD09zd/7+fndt8+NGzdmaZ8i6xpXLM7m2s8AcEtuUwlRoO08e4Pp27XHq8e/XINK7v95jPvmTa1fzS+/aLegvvgCVqwANzed0maRwQD9+mn9g2rX1qaJeP557dHyTAwdN/JZH5pVdON2chqDfj9MXGKK5TOL+1j8FtXIkSP55ZdfmD17NsHBwbz11luEhIQwaNAgQLt91Lt3b3P7yZMns3z5cs6dO8fJkycZM2YMS5YsYciQIeY2w4cPZ+PGjUyYMIHTp08zYcIENm/ezIgRIyx9OAWa0crAnW6vAOC6c0v6AbmEEAXG9dhE3loYhFLwaqMydKhV8t+VFy5ot6R27tTGrlmzBt5/P3f0tcmqypUhIAD69weTCd5+GwYM0K5OPYTRysCU7rUp6WLPxcgE3ll8DFXwxtTVn6Uf6VJKqWnTpilvb29la2ur6tatq3bs2GFe16dPH9WiRQvz9xMmTFAVKlRQ9vb2qmjRoqpZs2ZqzZo19+1z8eLFysfHR9nY2KgqVaqoJUuWZDqPPCb++I6FRqtTxcsqBerOD9P1jiOEyGEpqWmq6097lfd7q1XbyTvVneT/PFJ99KhSHh7aI9dlyih1/Lh+QbOTyaTUpElKWVlpx9a8uVIREY/cLDAkSlV6f63yfm+1mrHjIY/Oi0zLyue3TNUg/XGyRCnFjA5v8L81P3OjbiOKH96ndyQhRA76buMZvt96HkdbI6uGNvt3As2AAG1ahehoqFFD60z8n64F+cL69dCtG8TGaiMir1+vDSD4EH/su8KHy09gYzSwbHBTqpfKvhnOC6JcN1WDyD8MBgM2PXtgwkDxI/u1ie2EEAXC3vORTN12HoAvX67xb3GzZ4/WeTg6Gpo2hR078l9xA9C2Lezbp42yfPmyNlP50aMP3aRHozK0reZBSppi2IJA7iRn7rFz8eSkwBFZ1urZuuwvUx2A+F9/0zmNECInxCam8M5fx1AKujfw4oXapbQVe/ZoH/zx8dr0Bxs25L5HwLOTr692tapOHW1qh5Ytte8fwGAwMP7lGrg723HxRgKfrzmVc1kLOClwRJZ5F3PkcPPnAUiZ+0emnioQQuRtn606xd/Rdyjj6sBH7atqC4OCtAkt7xY3q1aBo6OuOXNE8eKwdat2tSo6WntibMuWBzYv6mjLd11rAzBvfwibTl3PmZwFnBQ44rG49uxOktGaopfOygzjQuRzm09dZ/HhqxgMMLFrLRztrOHiRa24iYvTpl9YtQocHPSOmnOKFNGuVj37LCQkaI+Rr3rw+GBNK7rx+lPlAXhvyTEiYmWwVEuTAkc8Fv9mVdhasREA0TPn6JxGCGEpUQnJjF56HICBzcvToKwrRERAmzYQHg41a2pj3BSk4uYuR0etqHnxRW0ww06dtKLnAd72r0xVT2duJSTz9uKjmExy9duSpMARj8WtsB3nWncEwLhwQabnaxFC5C0frThBZHwSlUoUZuSzlbUrNs89B+fPa08SrVunXc0oqOzsYPFi6NwZUlLgpZe0MYAyamptZEr32thZW7HrXCTzD4bkcNiCRQoc8di8e3Uixs4Rp8jrqB0yw7gQ+c2qo9dYfSwMo5WB77rWxl6lwcsvayP8urlpVytKlnz0jvI7a2uYN08r/O7c0aalOHgww6aV3J14t20VAMavPc3f0XdyMmmBIgWOeGyta3uzoWpzAG7NkNtUQuQnN+OT+GjFCQCGPF2RGqWc4c03YfNm7dbM2rXaSL9CY2sLf/2lPVUVF6fdwjt+PMOmfZuUpZ53UeKTUhmz9LiMcmwhUuCIx+ZoZ01Ye22GccdVy2WGcSHykc/XBBN9OwVfT2eGPFMRfvrp37mlFi+GBg30jpj7FCqkTdTZqBFERWkdkM+fv6+Z0crAhE41sbW2YufZGyw+fFWHsPmfFDjiidTo/rx5hvG0NWv0jiOEyAa7zt1gWeDfGAzaRJo2e3bDsGHayq++0p6eEhlzctL6JdWqBdeva+cqMvK+ZhXv9mkCPlt9iuvyVFW2kwJHPJHmPu5srtECgFuzftc5jRDiSSWmpPHhcu3WVB+/stQmTutAm5oKr7wCo0bpnDAPKFpUm8bB21u7gvPiixle4R7QrBy1SrsQl5jKB8vkVlV2kwJHPBEboxVxL3UGwGXLBm3ALyFEnvX9lnNcuXkbD2d73m7upT0VdOMG1K6t3aIyGPSOmDd4eGj9lFxctNGe+/TRZiT/D2ujFV93roWN0cDm4AhWBF3TKWz+JAWOeGL1XmzFpaKe2CYnkrp8hd5xhBCP6XR4LDN2XgTgk45VcRo+5N8nppYvL5hj3TyJqlVh2TKwsYFFi2DMmPua+Hg4MfSZSoB2qyr6dnJOp8y3pMART6xh+WJsrfUMAFGz5TaVEHmRyaR4f+lxUk0K/6rutDm4Hn7/HYxG7cPZ21vviHnT00/DrFna119/rXXWvsegFhWoVKIwNxOSmbD+dA4HzL+kwBFPzGhlIKlzFwCK7tyiPT0ghMhT/jwQwpGQaArbWfO5rzUMGaKt+Owz7UNaPL5eveCTT7SvhwyB7dvTrba1tuKLl2oAMP9AKIev3MrhgPmTFDgiWzTu8BTBxctinZZK8l9L9Y4jhMiCqIRkvt14BoB3nvKmxMC+cPs2tGoF772nb7j84qOPoEcPbdT3Ll3gypV0qxuWc6Vr/dIAvL/0BClppoz2IrJAChyRLep4FWFnHe02VcyvcptKiLxk4qYzRN9OwcfdiV4rpsPRo1q/m99/18a9EU/OYICZM6FuXe2x8Rdf1IrI/xjTzpeiDjacuR7H7N2X9MmZj8hPrsgWBoMBU7euALju261NxieEyPVOXovhz/3anEhTHEOxmjpVWzF3Lnh66pgsHypUSOt0XLw4BAVB//7wn0fDizra8v5zvgBM3nyOq1G3H7AjkRlS4Ihs07xNY4I8K2E0pZE4f6HecYQQj6CU4pOVpzApeLW0kSrvD9dWvPWWNq+SyH5lymhTOlhbw4IF8M036VZ3rleaRuVcuZOSxtgVJ2VsnCcgBY7INtVKOrO3XmsA4uf+oXMaIcSjrDx6jQOXb1HI2oqPl0+EmzehTh0YP17vaPnbU0/BlCna16NHw8aN5lUGg4EvXqqOjdHAltMRbA6Wq+GPSwockW0MBgPWr3QHwC3wAFyV+VWEyK0SklL5cm0wANPuHMF+y2aws4M//9T+KyzrjTdgwADtFlWPHul+X1Ys4cSA5uUBbWycxJQ0vVLmaVLgiGz1dKs67C9dDYA7f/ypcxohxINM23ae67FJ1DfE8fTMCdrCzz+HKlX0DVZQGAwwdao2QnRkJHTvDikp5tVDnq6Ih7M9IbduM/OfwRdF1kiBI7JVJXcnDjZ6FoDbv0uBI0RuFHrrNr/sugRK8fPOnzDExYGfn9b3RuQce3ttZnZnZ206hw8+MK9ytLNmzHNasTlt+3n+jr6jV8o8Swocke0cXu1OmsGKYqeOwoULescRQtxjwvrTJKeZ+Ch8D8X27tA+aOfM0UYtFjmrYkWYPVv7+ptvYOVK86qOtUrSsJwriSkmvlwTrFPAvEsKHJHtWreowR7vWgAk/DZP5zRCiP86EhLF6mNhlIqNoO/SadrCzz8HHx99gxVknTrB8H+eYOvTBy5fBrR+jeM6VMPKAGuOh7H3fKR+GfMgKXBEtitTzIGgpm0ASJZ+OELkGkopvlgTDEoxZ88MjPFx0KQJjBihdzTx9dfQsCFER0PXrpCsTbpZtaQzPRpp84CNW3WSVBnhONOkwBEWUeTVriRbWVP04hk4cULvOEIIYN2JcA5fiaLrmZ1UPrZPbk3lJra22qSmRYvCwYPw8cfmVW/7V6aogw1nr8fz+74rD9mJ+C8pcIRFPNu0CjvK1wMgTsbEEUJ3yakmvlp3Gpc7cYzb/s/s1h9/DJUr6xtM/MvbG375Rfv6669hyxYAijjYMqqNdgtx0qazRCUk65UwT5ECR1iEp0shTj3VDgDT/AXphiMXQuS83wIuE3LrNuP2/o5DzC2oWhXeflvvWOJeL78Mr7+u/c7s3Vt7hBzo3qAMVTyciE1MZcqWczqHzBukwBEWU+LVziRa2+Ly9xVt3hUhhC6ibyczdet56l09xUuH1moLf/pJuy0icp/vvtPGI7p2zTxfldHKwIfPVwXgj31XuHAjXueQuZ8UOMJinm1UkW0V6gMQ/as8TSWEXqZtO09C/B2+3fqjtuC116B5c31DiQdzdIT587UCdOVKrRgFmlVyo1WVEqSaFOPXymPjjyIFjrAYt8J2nG+pTdhnWLxIblMJoYNr0XeYG3CF/oeWUy7sEri5af07RO5WuzZM+GeE6ZEj4eRJAN5/3hdrKwObgyPYI4+NP5QUOMKiSr7amTvWdriEhcKRI3rHEaLAmbL5HCVuhjFyz3xtwbffQrFi+oYSmTNsGLRtC4mJ0KsXJCdToXhhejbWHhv/bPUp0kzyh+ODSIEjLKp1/fJsq9gAgFtz5GkqIXLS+Yh4Fh8O5eMtM7FLSYIWLbSOqyJvsLLSRjl2dYXAQG1ARmB4q0o421tzOjyOvw6H6hwy95ICR1iUi4MNV1o9D4Dxr8Vym0qIHDRx4xmaXAzE/9w+bayb6dO1SR5F3uHpae6Dw5dfwoEDFHW0ZVirSgB8s+Es8UmpOgbMvaTAERbn1aMzCTb2uFz/G3XwoN5xhCgQjoZGs+noVT7eOlNbMGSI9mi4yHu6dIFXXoG0NO0K3J079PYrS9liDkTGJ/HTdpnzLyNS4AiLe7puWbZXagRA5Gy5TSVETvh6w2l6Bq6lcmSI1udm7Fi9I4kn8cMP2tWcM2dgzBhsra0Y85wvADN3XZTZxjOQIwXO9OnTKVeuHPb29tSrV49du3Y9sO3SpUt59tlnKV68OM7Ozvj5+bFhw4Z0bX799VcMBsN9r8TEREsfingMjnbWXH22PQC2S/+S21RCWNjuc5GcOnaRt/b8MxfcF19oUwCIvMvVFWb9MwL1lCmwbRv+Vd1pVM6VpFQTX68/rW++XMjiBc7ChQsZMWIEH3zwAYGBgTRv3px27doREhKSYfudO3fy7LPPsnbtWg4fPszTTz9Nhw4dCAwMTNfO2dmZsLCwdC97e3tLH454TN49XibethAuN8JQ+/bpHUeIfEspxdcbTvP2rj9wSYyHWrVgwAC9Y4ns0K6dNsoxQL9+GOLi+Kh9VQwGWBF0jcCQKH3z5TIWL3C+++47+vfvz4ABA/D19WXy5Ml4eXnx448/Zth+8uTJvPvuuzRo0IBKlSrx5ZdfUqlSJVatWpWuncFgwMPDI91L5F4tanmzvbJ2mypi1u86pxEi/9p46jopRwJ55eg/V76//14m08xPvv0WypWDK1fgrbeoXsqFTnVLA/Dl2mCUXCE3s2iBk5yczOHDh/H390+33N/fn71792ZqHyaTibi4OFxdXdMtj4+Px9vbm9KlS9O+ffv7rvCI3KWQrZGwNh0BsF+xFEwmnRMJkf+YTIrJm84ydvMMjMoEXbvCU0/pHUtkJycnmDtXexpu9mxYtYpR/j7Y21hx8HIUm05d1zthrmHRAicyMpK0tDTc3d3TLXd3dyc8PDxT+5g4cSIJCQl07drVvKxKlSr8+uuvrFy5kvnz52Nvb0/Tpk05dy7jCciSkpKIjY1N9xI5r0KPl4mzLYRL5HXS9gboHUeIfGfDyXDK7NxA49ATKHt7+OYbvSMJS2jeXBvdGGDgQDxS4unfrBwAE9afJjVN/oCEHOpkbLhn3AWl1H3LMjJ//nzGjRvHwoULKVGihHl548aN6dmzJ7Vq1aJ58+YsWrSIypUrM3Xq1Az3M378eFxcXMwvLy+vJzsg8Via1ijN9ip+gNymEiK7mUyKqRuCeXfHXAAMb78NZcronEpYzOefa4/9X78Ow4fzvxYVcHW05cKNBBYduqp3ulzBogWOm5sbRqPxvqs1ERER913VudfChQvp378/ixYtonXr1g9ta2VlRYMGDR54BWfMmDHExMSYX6GhMvKjHuysjdxo+wIAjiuXyW0qIbLR2hNh1N34FxVu/Y2peHF49129IwlLsreHX3/VRjv+80+cN61n6DMVAZi0+Sy3k2XwP4sWOLa2ttSrV49NmzalW75p0yaaNGnywO3mz59P3759+fPPP3n++ecf+T5KKYKCgvD09MxwvZ2dHc7OzuleQh8Ve71MrK0DzrciSN21W+84QuQLaSbFjNVBjPjnsXCrsWNBfs/lfw0awNtva18PGkQPHxfKuDpwIy6JX3Zd0jdbLmDxW1QjR47kl19+Yfbs2QQHB/PWW28REhLCoEGDAO3qSu//zI0yf/58evfuzcSJE2ncuDHh4eGEh4cTExNjbvPJJ5+wYcMGLl68SFBQEP379ycoKMi8T5F7+fmWZIevVtxel9tUQmSL1ceu8ezq33C7HUNapUr/Pkos8r9PPoFKleDaNWzHvMe7bX0A+HnHBW7EJekcTl8WL3C6devG5MmT+fTTT6lduzY7d+5k7dq1eHtrs6GGhYWlGxPn559/JjU1lTfffBNPT0/za/jw4eY20dHRvP766/j6+uLv78/ff//Nzp07adiwoaUPRzwhG6MVt55/EQCn1Su0oceFEI8tNc3EvCV7GXBwOQDGCRPAxkbfUCLnFCr07wCAv/zC89dPUqu0CwnJaXy/JeNuGwWFQRXAh+ZjY2NxcXEhJiZGblfpICD4GtXqVMY5KYGUrduwebql3pGEyLOWHrlKSt/X6HZ8E2l+TTDu2S0TahZEQ4bAtGlQtiz7V2yn258nsLYysPGtpyhfvLDe6bJNVj6/ZS4qkeMa+niyo2pTAK7/8pvOaYTIu1LTTKz6YwNdjm8GwDjxWyluCqrx47Wn5i5fptEvE2lVpQSpJsU3G87onUw3UuCIHGe0MhDT8WUAnNeslNtUQjymZYF/03Plz1ihSH25E/j56R1J6MXJCWb+M3P8Dz8w1jUKKwOsOxHO4SsFcwoHKXCELnx7vEi0fWGcY26SvHWb3nGEyHNS0kxsm72MVhcOYjIasf5qvN6RhN78/aFfP1CKMu8M5ZXqxQH4al3BnMJBChyhizoVSrCzenMAwn+Rp6mEyKqlh0Pps2oGAKY+/bQnaYSYOBE8PeHsWcYcWlSgp3CQAkfowsrKQHzHlwAoun4VpMqgVEJkVkqaif0/L6DR1ZOk2tpi/clYvSOJ3KJoUfhnMuvC309ijPttoGBO4SAFjtBN9Z4vcquQM06xUSRu3qp3HCHyjOVHrtJvzT/9LQYPhtKl9Q0kcpcXXtAmWjWZ6Dn7C4rbGwvkFA5S4Ajd1Cjrxu4ad29TydNUQmRGmklxYuocaly/QHIhR6zff1/vSCI3mjIFihTBGBjItJu7AG0Kh4SkgnO1XAocoRuDwUDii9rTVG4bVsttKiEyYc2REHqt+UX75q23oHhxfQOJ3MnDwzybfIPZk2lkiC1wUzhIgSN0VaPni9ws5Ezh+BgSNmx69AZCFGAmk+LMxB+peOsqiU5FsH13lN6RRG722mvw1FMYbt9m6q6ZoBQzdhacKRykwBG6qlK6KHtrtQAgQp6mEuKhNgVd4ZW1c7RvxowGFxd9A4nczcoKfv4ZbG0psWcbQyIOFagpHKTAEboyGAwkvdwJgOKb1kBKis6JhMidlFKc++oHSsdGEO9aHPsRw/SOJPKCKlXggw8AGLZqOi534vjzQAgXb8TrHMzypMARuqvd4wVuOBShcEIscWs36B1HiFxp+/FQXlqvdca3ev99bZJFITLjvffA1xfbmzf4IfBP0kyKr9fn/ykcpMARuqtYsgj767QE4MYsuU0lxL2UUpz+ciql4m4QV6wEDm8O0juSyEvs7MzTODTftYomIcdYfzKcw1du6RzMsqTAEblCSqfOAJTYsg6Sk3VOI0TusvfUNTqunat9M3oM2NvrG0jkPU2bwiCtMJ6y/SfsUpP5Yk3+nsJBChyRK9Tr0ZEIx6IUvh1HzKr1escRIlc59eUUSsXdINa1BE5D5OqNeEzjx4OnJ8XDQhixfzFHQqJZfyJc71QWIwWOyBXKlHDiQL2nAbgxWwb9E+Kug6fDeG7VrwCo0e/J1Rvx+IoUgalTAXg9YDGVb1zmq/WnSU7Nn1M4SIEjcg3VuSsAnts2QFLBGKdBiEc58cVkSsXdIMa1BC5DB+sdR+R1L78MHTtiTEvlm03TCYmMZ97+K3qnsggpcESuUa9He64XdsXxTjy3lq/WO44Qujt6/jr+K7Rxb0zvytUbkQ0MBvjhByhcmFqhp+gRuI7vt5wj5k7+G6JDChyRa5R0deRQ/VYA3Jzzh85phNDfsc/+uXpTtDhFh8vVG5FNvLzgyy8BGLNzLrbXw/hx+wWdQ2U/KXBErmLopt2mKrljEyQm6pxGCP2cC4nkmWWzAEiWqzciuw0eDI0a4Zh0m082/8zsPZf4O/qO3qmylRQ4Ilep/8pzhDkVwzExgRtLVukdRwjdBH02iVJxN4guWpziI97UO47Ib4xGmDEDZW1N27MBPH1qNxM35K/B/6TAEblKCRcHAhu2BiDqV7lNJQqmq+FRNF2kDcyWMHKUXL0RllGzJoZ33gHgk00/sWn/OU78HaNzqOwjBY7Iday7dwOg9K5NcCd/XTIVIjOCPplEydgb3CpSnFKjZM4pYUEffQQVKuARf4t3ts9l/Lr8M/ifFDgi16nfrR3XnIvjkHSH8EXL9Y4jRI66eSuOun/+BEDUsJFy9UZYVqFC2ozjQM/AtdzZsZvtZ2/oHCp7SIEjch1XJ3uONn4WgJi5f+qcRoicdfjz7ykZe4ObzsUoP3q43nFEQdCqFfTpgxWKL9f/wLcrj5NmyvtXcaTAEbmS7SvabaoyezbLbSpRYMTfTsJn7nQAIl4fgkFmDBc55dtvMbm5USXyCi1W/8Zfh0P1TvTEpMARuVL9rm256lKCQsmJ/P3nUr3jCJEjDnz9E963rhHj4IzPR2/rHUcUJG5uWE2aBMDwPfNZ9OdWbien6hzqyUiBI3IlFwdbTjRpA0Dcb/N0TiOE5SWlpOL10xQAQnsNxMrZSedEosDp0QNT69bYpaXw9tJJ/LLzot6JnogUOCLXKtSjOwDeAdtQ8fE6pxHCsg5M/Y1K1y+RYOdApc9G6x1HFEQGA1Y//0yavT1NQo4RPvVnrsfm3QFXpcARuVb9Ts8SUsSDQimJhP62WO84QlhMWpqJYlO+BeB8p17YFXfTOZEosMqXx+qTTwB4Z+NMpi8M0DnQ45MCR+RajvY2nHqqHQB3/pDbVCL/OjRnCVVDgkm0tqXi+I/0jiMKOMPIkdypVoOiiXHUnvwpQaHRekd6LFLgiFytcO8eAJQ7sBMVHa1vGCEsQCmF/TdfARD8fFccy5TSOZEo8KytKTRnFiaDFS+d2s6KCbPz5OB/UuCIXK1+hxZccPPCNi2Fy7Pn6x1HiGx37K8N1Dp7hBQrI+W+Gqt3HCE0DRqQ+IY2g/1rf3zN6oDzOgfKOilwRK5mb2vN2RbPAZD6pxQ4Iv9J/eILAI4/05EiVSrqnEaIfzlMGE+ce0m8Yq4TPfpDEpLy1mPjUuCIXM+lb08AygXuJe1GpM5phMg+Zzbupt7R3aQZrCj5pVy9EblM4cLY/fwjAK/s/ouls1bpHChrpMARuV69tn6cdi+PtSmNSzN+1zuOENkmduxnABxr3BqPBrV0TiPE/Wxf6EhYm45YKxN1PnuX0BtxekfKNClwRK5nZ23kUuv2AKiFC3VOI0T2CNkfRN39mwFw/WKcvmGEeAiPOT+RUKgw1cPPs3/kJ3rHyTQpcESe4D6gDwDlTxwk6e9rOqcR4smFv/8pRmXiaO1meD/tp3ccIR7I4OlJ7KdaX7F2C6dxZFeQvoEyKUcKnOnTp1OuXDns7e2pV68eu3btemj7HTt2UK9ePezt7Slfvjw//fTTfW2WLFlC1apVsbOzo2rVqixbtsxS8UUuUPupOpwsXQWjMnFh+ly94wjxRK6fvkDt7Vp/BvuPP9Q5jRCP5jlyCJer1sUxJZHUQW+QlmbSO9IjWbzAWbhwISNGjOCDDz4gMDCQ5s2b065dO0JCQjJsf+nSJZ577jmaN29OYGAg77//PsOGDWPJkiXmNgEBAXTr1o1evXpx9OhRevXqRdeuXdm/f7+lD0foxMrKwLW2LwBg+9cindMI8WQufPAFtqZUgivWwuelNnrHEeLRrKwo8ttsko02NDy1j4DxP+qd6JEMysKj9zRq1Ii6devy44//ngxfX19efPFFxo8ff1/79957j5UrVxIcHGxeNmjQII4ePUpAgDZkdLdu3YiNjWXdunXmNm3btqVo0aLMn//oR4ljY2NxcXEhJiYGZ2fnJzk8kYNOHzxFlYbVAIg7dxGniuV0TiRE1kWH3cC6rDeFk+9w7Kc/qPm/HnpHEiLTAvuPoM7sKdx0LILx9GmKlHbP0ffPyue3Ra/gJCcnc/jwYfz9/dMt9/f3Z+/evRluExAQcF/7Nm3acOjQIVJSUh7a5kH7TEpKIjY2Nt1L5D0+9X05Vr4mABemzdE5jRCP58TYbyicfIfLHuWoMaC73nGEyJLqU8dzxd2bYgnRnO03WO84D2XRAicyMpK0tDTc3dNXeO7u7oSHh2e4TXh4eIbtU1NTiYyMfGibB+1z/PjxuLi4mF9eXl6Pe0hCRwaDgVvPvwiA0/IlD28sRC50Oy4BnwWzAIgaPAyD0ahzIiGyxsahELenTgeg4ealnF20WudED5YjnYwNBkO675VS9y17VPt7l2dln2PGjCEmJsb8Cg0NzVJ+kXtUfKMvaQYrKlw+ReTR4EdvIEQucuTLqRSPu0WES3FqjBqkdxwhHotvl+cIaN0ZAIchg0lNuK1zooxZtMBxc3PDaDTed2UlIiLiviswd3l4eGTY3trammLFij20zYP2aWdnh7Ozc7qXyJtK+5bjROU6AFyaPlvnNEJkXkpKKl6/aH/5hvb5H9aF7HVOJMTj85nzAxGFXSl9I5STg0bpHSdDFi1wbG1tqVevHps2bUq3fNOmTTRp0iTDbfz8/O5rv3HjRurXr4+Njc1D2zxonyJ/SXhR+8uh2Jrl+gYRIgsOfj8X78hQ4uwdqTb2bb3jCPFEXEu7c/qjrwCoNu9nbu4M0DlRBpSFLViwQNnY2KhZs2apU6dOqREjRihHR0d1+fJlpZRSo0ePVr169TK3v3jxonJwcFBvvfWWOnXqlJo1a5aysbFRf/31l7nNnj17lNFoVF999ZUKDg5WX331lbK2tlb79u3LVKaYmBgFqJiYmOw9WJEjIq9cU8lWRqVAhe49rHccIR4pLTVNnfCuphSow68O0juOENkiLc2kdtZtpRSoq2UqKZWUZPH3zMrnt8ULHKWUmjZtmvL29la2traqbt26aseOHeZ1ffr0US1atEjXfvv27apOnTrK1tZWlS1bVv3444/37XPx4sXKx8dH2djYqCpVqqglS5ZkOo8UOHlfYI0mSoHa23uo3lGEeKQDv61QClSi0UbFXQrRO44Q2ebU0fPqZiFnpUBdHPaexd8vK5/fFh8HJzeScXDyvoOfTaHBxyO4UqIMZcIuYbCSWUdE7qSU4mCt5jQ8voegdl2pvVbmUxP5y5JR39Bp4rukGK1JOXAQh7q1LfZeuWYcHCEsxXdQL5KMNnhHhHBuS8bjHwmRGxzbGEDD43swYaDM5x/pHUeIbNf28xHs8m2CTVoqUd17QWqq3pEAKXBEHlW4uCvBdZoBEDHjN53TCPFgsZ99CUBw42dwrVtd5zRCZD9Hextsfv6JWDtHSp07wdWxX+odCZACR+Rhxu7dACi7ZXWemPhNFDxnDp2iUcAGAIp9IldvRP7VuHkN1vV7B4DiX39B0qnTOieSAkfkYT4DXuWOjR2lo8I4vnyL3nGEuE/ouK+wNaVyzrceHv4t9I4jhEW1+XY0+yrUxS41mRvdeoFJ3z88pcAReZatixPnGj4NQMyvv+ucRoj0Qi7+TaNNfwFg9/5ondMIYXlFHO1I/OFHEmzsKX3iEGFfTdI1jxQ4Ik+z7/kqAD471nEnMUXnNEL869TYb3BKvsPVUhUo06OT3nGEyBEt2zZkVfehALh8+jGpkTd1yyIFjsjTKvbuTJy9Ix5xkRz+Y7necYQAICIimrrLtM7vSSPfhofMvSdEfvPM9+NYVbMVs0ZNItHJRbccUuCIPM3KoRCXW7YDIPW3eTqnEUJz6IuplEiI4kZRd8oP6a93HCFyVIkiDjTctZqhn79OYTtr3XJIgSPyvOL/6wdAnQObuX4jRuc0oqCLiU/Ed97PAEQNHIzB1lbnRELkPHdn/SeTlQJH5HkeHdtys0hxXJISCPr5T73jiAJuz3ezKXfzb+IKFabi+yP0jiNEgSUFjsj7rKy4/vxLADgsXkABnH1E5BJ3klLxmjkVgGuvvoaVi0wFI4RepMAR+YLXkAEANDwZQPDpUJ3TiIJqx6wl1Lh6miRrGyp8Ko+GC6EnKXBEvuDUqD5hpcpjl5bCuR/n6h1HFEApaSacvtfG/bjSvgvWJT11TiREwSYFjsgfDAZud9GmbvBYs4wUmbpB5LBtf22l6Zn9mAwGvL/8WO84QhR4UuCIfMP7Te1x3AYXgwjYdVznNKIgMZkU6ttvAbj0VBvsfH10TiSEkAJH5BvWFSsQ6lsbKxQRM3/VO44oQHZuPcIzRzYD4PG5XL0RIjeQAkfkK9Y9ewJQZetqom8n65xGFARKKaK//AYbUxohNRvi2MxP70hCCKTAEfmM5+t9SLUyUj38PDtX7tI7jigA9h+5QOs9KwFwGfehzmmEEHdJgSPyFzc3rjV6CoDEuTLDuLC8K59/S+HkO4R7V8LlxfZ6xxFC/EMKHJHvuAzoA0CjfRu4GBGncxqRnx07F84zGxcCYDvmPZlUU4hcRAocke+4dOtMol0hvKPDCZi3Ru84Ih87Nv57it+O5pabB66v9dY7jhDiP6TAEfmPoyORrbUZxu0WL8RkkqkbRPY7HxZNk+XaoJJpw0eAjY2+gYQQ6UiBI/KlEoNeA6Dl0W3sPxuucxqRH+3+dhblo66R4OhM8RFv6h1HCHEPKXBEvmTbtg1xLq643Y7h+NwlescR+czfUbepM38GAHH9X4fChXVOJIS4lxQ4In+ytubOS50A8Fy1hLjEFJ0Difxk0/SF1Ao7S7KNLR4fvKN3HCFEBqTAEflW8UHa1A2tzwSwbu9ZndOI/CIyPonys6cBcLNLDyhRQudEQoiMSIEj8i1Dw4ZElalAodQkwmf/oXcckU+s/n09T108TJrBCo9P3tc7jhDiAaTAEfmXwYBtP21MnIY7V3MmXMbEEU8mNjEFtx+nABDh3x5DxYo6JxJCPIgUOCJfc+zfF5PBQOPQE2xYFaB3HJHHLV26h7YndgDgLpNqCpGrSYEj8jcvL6IbNQPAev48klLTdA4k8qqEpFRsv5+CtTIR0ag5VvXr6R1JCPEQUuCIfM/ln87G7YI2sfnkdZ3TiLxq8YYgXjyyDoBin8ikmkLkdlLgiHzP2KkTyfYOlIsK4/DCtXrHEXnQneQ0EqdMxSEliSif6hj9n9U7khDiEaTAEflf4cIkv/gSABXXLeHv6Ds6BxJ5zeJdZ+gSsBwAp4/HyKSaQuQBUuCIAqHwQG3qhvbBu1i294LOaURekpSaRsTkHyl2J5a4kl5Yd+2qdyQhRCZIgSMKhpYtue1REuekBCLmLZIJOEWmLdl/mW67FgNgP/pdsLbWOZEQIjOkwBEFg5UVtn16A9Bi/3p2n4/UOZDIC1LSTJz9YQ5eMddJLOKKTf/X9I4khMgkKXBEgWHdry8ALS4eZvWGI/qGEXnCsiNX6bJ1PgDG4cPAwUHnREKIzLJogRMVFUWvXr1wcXHBxcWFXr16ER0d/cD2KSkpvPfee9SoUQNHR0dKlixJ7969uXbtWrp2LVu2xGAwpHt1797dkoci8gMfH+7Ua4C1MuG6bBHXYxP1TiRysTST4sCMBVSLuEiKfSFshg7RO5IQIgssWuC8+uqrBAUFsX79etavX09QUBC9evV6YPvbt29z5MgRPvroI44cOcLSpUs5e/YsHTt2vK/twIEDCQsLM79+/vlnSx6KyCcKDXodgM5HN7LoQIjOaURutvrYNV7aNE/7ZsAAKFZM30BCiCyxWG+54OBg1q9fz759+2jUqBEAM2fOxM/PjzNnzuDj43PfNi4uLmzatCndsqlTp9KwYUNCQkIoU6aMebmDgwMeHh6Wii/yq65dSR06jIq3rnL8r/WkPVMJo5U88ivSM5kUG+euZtqVY5isjNi8M0rvSEKILLLYFZyAgABcXFzMxQ1A48aNcXFxYe/evZneT0xMDAaDgSJFiqRbPm/ePNzc3KhWrRqjRo0iLu7BEykmJSURGxub7iUKKGdnDF26APBMwBq2n4nQOZDIjTacDKfdOm0G+tRu3eA/f1wJIfIGixU44eHhlChR4r7lJUqUIDw8PFP7SExMZPTo0bz66qs4Ozubl/fo0YP58+ezfft2PvroI5YsWcLLL7/8wP2MHz/e3A/IxcUFLy+vrB+QyDeMAwcA0P70Lv7acVrnNCK3MZkUixZso91Z7Q8x2zGjdU4khHgcWS5wxo0bd18H33tfhw4dAsCQwWifSqkMl98rJSWF7t27YzKZmD59erp1AwcOpHXr1lSvXp3u3bvz119/sXnzZo4cyfjJmDFjxhATE2N+hYaGZvWwRX7SrBkp5SpQOPkOhVct42rUbb0TiVxk/clwWq39A6MykeLfFmrU0DuSEOIxZLkPzpAhQx75xFLZsmU5duwY16/fP7HhjRs3cHd3f+j2KSkpdO3alUuXLrF169Z0V28yUrduXWxsbDh37hx169a9b72dnR12dnYP3YcoQAwGbAb2h/ffp8uxTSw8+AZv+9/fJ0wUPGkmxdwlAfx2XOsLaPO+XL0RIq/KcoHj5uaGm5vbI9v5+fkRExPDgQMHaNiwIQD79+8nJiaGJk2aPHC7u8XNuXPn2LZtG8Uy8eTCyZMnSUlJwdPTM/MHIgq2Pn1QH35Iw6un+HrtXlJaVcLGKMNCFXRrjofxzLp52KWlkurXBOunntI7khDiMVnsN7qvry9t27Zl4MCB7Nu3j3379jFw4EDat2+f7gmqKlWqsGzZMgBSU1Pp3Lkzhw4dYt68eaSlpREeHk54eDjJyckAXLhwgU8//ZRDhw5x+fJl1q5dS5cuXahTpw5Nmza11OGI/KZkSVTbtgC02reWzafuv9ooCpY0k2LWykP0DNRmnLf+8AOZVFOIPMyif7LOmzePGjVq4O/vj7+/PzVr1uT3339P1+bMmTPExMQAcPXqVVauXMnVq1epXbs2np6e5tfdJ69sbW3ZsmULbdq0wcfHh2HDhuHv78/mzZsxGo2WPByRz1j17w9ApxNbmLdHJuAs6FYe/ZuWGxbimJJIWs2a0K6d3pGEEE/AorPGubq68scffzy0jVL/TnpYtmzZdN9nxMvLix07dmRLPlHAtW9PmpsbJSIjsdu8kbMv1aKyu5PeqYQOUtNMzFh9lPmHVwJg/ECu3giR10mnA1Fw2dpi7K1NwNn96Ebm7r2sbx6hm2WBf9Ns61KKJMZjqlgJOnXSO5IQ4glJgSMKtgHamDjPXDjInu1BxNxJ0TmQyGkpaSZ+3nCKgQe1voBWY0aD3O4WIs+TAkcUbL6+qObNMSoTLxxez+JDMkZSQbP0yFUa7VxJiYQoTF5e0LOn3pGEENlAChxR4BkGDQKg27GNzNt9kTTTw/uBifwjOdXEtI1nGLR/CQBW77wDtrY6pxJCZAcpcITo1AlVrBgl4yIpf3gn207L/FQFxeLDodTdtwGvmOuo4sXhnyfrhBB5nxQ4QtjZYejbF4BXg9YzN+CyrnFEzkhKTWPa5rMMDlgMgOGtt8DBQedUQojsIgWOEACvvw7A0xcOcfHQKc5HPHh2epE/LDgQSvXDO6h8MwTl7AyDB+sdSQiRjaTAEQKgcmV4+mmsUHQ7uoG5e6/onUhYUEJSKlO3nOPNgEUAGIYMARcXnVMJIbKTFDhC3PW//wHQ7fgmVhy8LI+M52Nz9lyiyon91Ao/hypUCIYP1zuSECKbSYEjxF0vvYQqXhz3+Fv4BQew4ECI3omEBUQlJPPz9gsM2zsfAMPAgVCihM6phBDZTQocIe6ytcXw2muA1tl4zp7LJKeadA4lstuPOy5Q/dwRGl49hbKzg3ff1TuSEMICpMAR4r8GDgSg+eVAbEIus+roNZ0DiewUFnOHX/dcYsTuPwEwvP46lCqlcyohhCVIgSPEf1WoAG3aYKUUvY6sYeaui4+cAFbkHd9vOUe9i0dpdPUkytYW3ntP70hCCAuRAkeIew0ZAmidja+E3GDnuUidA4nscOFGPIsOXWXEHrl6I0RBIAWOEPdq1w7Kl8clMZ6XTm1j5s6LeicS2eC7jWdpcPkojUJPaNMxyNUbIfI1KXCEuJfRaL6K0/fwanafu8GJv2N0DiWeRGBIFGuOh5n73jBwIJQurW8oIYRFSYEjREb69QMHBypHXsEv5Di/7JKrOHmVUoov1wbTOOQYje9evRk9Wu9YQggLkwJHiIwUKQK9ewPQ58gqVh0L4+/oO/pmEo9lw8lwDl6O4q29C7QFAwbI1RshCgApcIR4kH9uU/mf249H1HVm776kcyCRVcmpJr5ad5pGIcdpdOWYXL0RogCRAkeIB6lWDVq1wkqZ6Bm4lvkHQriVkKx3KpEF8/Zf4fLN24zat1Bb0L8/eHnpG0oIkSOkwBHiYYYOBaDH8Y2kJdxm1m7pi5NXxNxJYcqWczQMPUGDS0FgYwNjxugdSwiRQ6TAEeJh2reHsmVxvh3LC6d2MHfvFaJvy1WcvGD6tvNE305hzAFtxnAGDJCrN0IUIFLgCPEwRiMMHgzAG0dXE5+Ywpw9l/XNJB4p9NZt5uy5TMPQE9Q5f0S7eiN9b4QoUKTAEeJRBgwAR0fKhV3kqUtHmLPnEnGJKXqnEg/x1frTJKem8ekBbcZwBgyAMmX0DSWEyFFS4AjxKEWLmifhHB60ktjEVH4LuKJzKPEgARdusuZYGE9fOkyV80fB3h4+/FDvWEKIHCYFjhCZMWIEGI3UO3eYatcv8MuuiyQkpeqdStwjNc3EJ6tOYlAmvjj8z7g3Q4dCyZL6BhNC5DgpcITIDG9v6NoVgOFHVxF1O4U/9slVnNzmzwMhnA6Po/PFfZS8eBqcnGTOKSEKKClwhMisUaMAaH1sGyVjI5i56yJ3ktN0DiXuikpIZuLGsxhNaXx4t+/NqFFQrJi+wYQQupACR4jMqlsXnnkGq7Q0hh5fS2R8Mr/vu6x3KvGPiZvOEHMnhTdD9+AScgnc3OCtt/SOJYTQiRQ4QmTFP1dxOh9Zh3NiPNO2XSDmjjxRpbdT12L5c38ItqkpvLljnrZwzBjtFpUQokCSAkeIrGjbFqpXx+Z2AkPObyPmTgozd8roxnpSSjFu1UlMCr6I2INd2N9QqhS88Ybe0YQQOpICR4isMBjg7bcB6H1wBTZpKczafYkbcUk6Byu4lh75mwOXblHMlMjL6+ZqCz/+GAoV0jeYEEJXUuAIkVWvvgolS2IfEc6wa/u5k5LGD1vP6Z2qQIpKSOaLtcEAzLi2BWPkDfDxgX79dE4mhNCbFDhCZJWtrfkqzsBdCzCa0vjzQAghN2/rHKzg+WrdaW4lJNPE7jZ1l8zRFk6YoE3NIIQo0KTAEeJx/O9/ULw49qGXeefmYVLSFJM2n9U7VYFy4NItFh4KBeD7k0sxJCZC8+bQsaPOyYQQuYEUOEI8DkdH8xNV/bb/iZUpjeVBf3M6PFbnYAVDcqqJD5YdB+CtErdxW7pQW/Htt1o/KSFEgScFjhCP6403wNUVu4vn+TDhBErBhHWn9U5VIMzcdZFzEfEUc7Rl8JqfQSno1g0aNtQ7mhAil7BogRMVFUWvXr1wcXHBxcWFXr16ER0d/dBt+vbti8FgSPdq3LhxujZJSUkMHToUNzc3HB0d6dixI1evXrXgkQiRAScnGDkSgJ6bf8PGoNh25gbbz0ToHCx/u3Izge+3aJ26v3e9js3WLVqfmy+/1DmZECI3sWiB8+qrrxIUFMT69etZv349QUFB9OrV65HbtW3blrCwMPNr7dq16daPGDGCZcuWsWDBAnbv3k18fDzt27cnLU2GzRc5bMgQKFIE27Nn+EppH7qfrj5FcqpJ52D5k1KK95cdJynVRLPyRWjy89faiiFDoHx5fcMJIXIVixU4wcHBrF+/nl9++QU/Pz/8/PyYOXMmq1ev5syZMw/d1s7ODg8PD/PL1dXVvC4mJoZZs2YxceJEWrduTZ06dfjjjz84fvw4mzdvttThCJExFxdtpnHgxbVzKO5gzcUbCfwWcFnXWPnVvP0h7Dl/E3sbKyYlBGE4fhyKFIEPP9Q7mhAil7FYgRMQEICLiwuNGjUyL2vcuDEuLi7s3bv3odtu376dEiVKULlyZQYOHEhExL+X/A8fPkxKSgr+/v7mZSVLlqR69eoP3G9SUhKxsbHpXkJkm2HDwMkJ4/HjTCoUAsCUzedk8L9sFnrrNl/+M+bNh01KUnz8J9qKjz+G//wRJIQQYMECJzw8nBIlSty3vESJEoSHhz9wu3bt2jFv3jy2bt3KxIkTOXjwIM888wxJSUnm/dra2lK0aNF027m7uz9wv+PHjzf3A3JxccHLy+sJjkyIexQtqhU5QNN506jp6URcUirfbnj4lUqReSaT4t2/jnE7OY2GZV3psX423LgBvr7a7SkhhLhHlguccePG3dcJ+N7XoUOHADBk8LimUirD5Xd169aN559/nurVq9OhQwfWrVvH2bNnWbNmzUNzPWy/Y8aMISYmxvwKDQ3NwhELkQlvvQXOzhiOHmWyQXuSatHhUI5djdY3Vz4xb/8VAi7epJCNkck1rDFMm6atmDJFBvUTQmQoywXOkCFDCA4OfuirevXqeHh4cP369fu2v3HjBu7u7pl+P09PT7y9vTl3TuvA6eHhQXJyMlFRUenaRUREPHC/dnZ2ODs7p3sJka2KFYP33gOg/JQJdK5RAqVg3MqTKKV0Dpe3hdy8zfh/Hr9/r01lSo4dA2lp8NJL8OyzOqcTQuRWWS5w3NzcqFKlykNf9vb2+Pn5ERMTw4EDB8zb7t+/n5iYGJo0aZLp97t58yahoaF4enoCUK9ePWxsbNi0aZO5TVhYGCdOnMjSfoXIdsOHg4cHXLzIx2G7cbA1ciQkmsWHZQiDx2UyKd5dcpTbyWk0KudK7/BA2LIF7Oxg4kS94wkhcjGL9cHx9fWlbdu2DBw4kH379rFv3z4GDhxI+/bt8fHxMberUqUKy5YtAyA+Pp5Ro0YREBDA5cuX2b59Ox06dMDNzY2XXnoJABcXF/r378/bb7/Nli1bCAwMpGfPntSoUYPWrVtb6nCEeDRHRxg7FgDnb75ilJ9WlH+++hQRcYl6JsuzZuy6yL6Lt3CwNfLt85WxGqXNAca770K5cvqGE0LkahYdB2fevHnUqFEDf39//P39qVmzJr///nu6NmfOnCEmJgYAo9HI8ePHeeGFF6hcuTJ9+vShcuXKBAQE4OTkZN5m0qRJvPjii3Tt2pWmTZvi4ODAqlWrMBqNljwcIR6tf3+oVAkiIuizbxk1SrkQm5jK2BUn9U6W5wSFRps7an/cvipes6fBlSvg5QWjR+ucTgiR2xlUAewgEBsbi4uLCzExMdIfR2S/RYu0aQMKF+bMniCeX3CGVJPixx51aVfDU+90eUJcYgrPf7+bkFu3eb6mJz/UL4yhZk1IStLOb5cuekcUQuggK5/fMheVENmtc2eoVw/i4/GZ9T1vtKwAwEcrThJ9O1nncLmfUooPlp0g5NZtShUpxJcvVsfwxhtacfPss9r5FUKIR5ACR4jsZmUFEyZoX//4I0PKWlGhuCOR8Ul8viZY32x5wJIjf7Py6DWMVga+f6UOLn8tgK1boVAh+OknmS1cCJEpUuAIYQmtWoG/P6SkYPfeu3zduSYGA/x1+Co7z97QO12udfFGPB+vOAHAyGcrU88xzTyhKePGyXxTQohMkwJHCEuZNAmsrWH5cuoFH6CPX1kARi85RsydFH2z5UIJSakMnneE28lp+JUvxqAWFeDtt+HmTahZUxtMUQghMkkKHCEspWpV8xQODBvGOy3L4l3MgWsxiXy4/IQMAPgfSine+esop8PjKO5kx+TutTFu3QK//abdkpo5U0YsFkJkiRQ4QljS2LHg7g7nzuH44w9M7lYbo5WBVUevsTzob73T5RrTt19g7fFwbIwGfupZF3cbBYMGaSuHDIGGDfUNKITIc6TAEcKSnJ3hm2+0rz/7jDpWCYxoVQmAj5af5HJkgo7hcodtpyP4dqM23s2nL1SnnrcrfPghXLgApUvDF1/onFAIkRdJgSOEpfXsCU2bQkICvPMOg5+uSMNyrsQnpfLGvCMkpqTpnVA3F2/EM2xBIEpBj0ZleKVhGdi+Xeu/BNpTU/8Z5FMIITJLChwhLM1ggB9+0B4fX7AA484dfN+9DsUcbQkOi+WTVQVzlOOYOym8/vth4hJTqe9dlLEdqkFsLPTtC0rBwIHw/PN6xxRC5FFS4AiRE2rX/rdPyZtv4lHIiind62AwwPwDoSw6GKprvJyWmJLGwN8OcT4iHg9ne6b3rIuttRWMGKFNx1C+PHz3nd4xhRB5mBQ4QuSUzz6D4sXh1CkYP55mldx4q3VlAD5cfoLDV27pHDBnpJkUIxYEceDSLZzsrJndtwElnOxhxQqYM0e74jV3LhQurHdUIUQeJgWOEDnF1RWmTtW+/uILOHmSIU9XpE01d5LTTPzv9yNci76jb0YLU0rx8YoTrD8Zjq3Rihm961O1pDNERGi3pADeeQeaNdM3qBAiz5MCR4ic1LUrdOwIKSnQvz9WysR3XWtTxcOJyPgk+s89RFxi/h0E8Pst55m3PwSDASZ3r41fhWL/9re5cQNq1IBPP9U7phAiH5ACR4icZDDA9Ona4+P798O33+JoZ83M3vVxK6x1On7jjyMkp5r0Tprtft93hUmbzwLwacdqPHd3ZvVJk2DlSm0gv99/Bzs7HVMKIfILKXCEyGmlSsGUKdrXH30ER4/i5erAnL4NcbA1svt8JO8tOYbJlH9GOp63/wofLdfmmBr2TEV6/TNtBbt3w7vval9Pngy1aumSTwiR/0iBI4Qe+vSBF1/UblX16gVJSdQo7cK0HnUxWhlYFvg3H63IH9M5zNt/hQ+WacVN/2bleOtZrWM1ERHQrRukpcErr8Abb+iYUgiR30iBI4QeDAaYMQNKlIDjx+G99wB42qcE33WthcEA8/aH8Nnq4Dxd5Py044K5uBnQrBwfPu+LwWDQippXX4Vr18DXVzsXBoPOaYUQ+YkUOELopXhxmD1b+3rKFK0fCvBC7VJM6FQTgNl7LvHxipN57naVyaQYvzaYr9adBmBQiwp8cLe4ARg3DrZsAUdHWLJEHgkXQmQ7KXCE0NPzz8PIkdrXfftCSAgAXet7Mf7lGhgMWufctxcfJSUtb3Q8TkxJY+iCQH7eeRGA95+rwuh2Vf4tblavhs8/176eMUO7giOEENlMChwh9DZ+PDRoAFFR2mPkSUkAvNKwjHn28WWBf9N/7iFic/kj5BGxiXSbsY81x8KwMRr4tkstXn+qwr8Njh/X+tsADB6s3aYSQggLkAJHCL3Z2sKCBVC0qPbo+JAh2tgwaLerfu5Zj0I2RnaevUHnH/cSeuu2zoEzFnDhJs99v5ujodEUcbDh9/6N6Fyv9L8NIiKgQweIj4enn9aemhJCCAuRAkeI3KB8eZg/X5uQ85df4OefzataV3Vn8SA/3J3tOHs9nvZTd7P51HUdw6aXmmbih63n6PHLPiLjk/Bxd2L54KY0Ll/s30YJCdoAh1euQKVK8Ndf2rg3QghhIVLgCJFbtGkDX36pfT10KGzebF5VvZQLK95sRi2vIsTcSWHAb4f4bPUpElPSdAqruXgjni4/B/DtxrOYFLxctxTL32xKWTfHfxulpECXLtrVKVdXWLVK+68QQliQQeXlZ1AfU2xsLC4uLsTExODs7Kx3HCH+pZQ2Ls68edpox3v2QPXq5tXJqSa+Wnea2XsuAVDezZGvO9ekftmcLRgSU9L4accFpm+/QHKqCSc7a8Z2rEanuqX+7UwMYDJBv37w229QqBBs3QqNG+doViFE/pGVz28pcKTAEblNUhL4+8POneDlpRU5Xl7pmmwJvs6YpceJiNM6JL9ctxTvtPHB06WQRaOZTIrVx8OYuPEMV25qfYGaV3Ljq041KVXknvdWShu87+efwWjUZgt//nmL5hNC5G9S4DyCFDgi17t1C5o0gTNnoHJlrdhxd0/XJOZOCl+sOcWiQ1cBsLexomcjb/o3L5fthU5Kmon1J8KZtu08p8PjAHB3tuPD56vSvqZn+qs2oBU3w4drs6cbDNocUz16ZGsmIUTBIwXOI0iBI/KEkBBo3lz7b40asG0bFCt2X7OjodF8tvoUh65EAWBjNPBcDU+61POiSYViWFk9/gjBlyITWBl0jQUHQwiLSQTAyc6aAc3L0795OQrbWd+/UVoavPnmvx2l58zRxvgRQognJAXOI0iBI/KM8+e1Iic8XCtyNm4ED4/7miml2H72Bj9uv8CBS7fMy0s42dGicnGaVy5OzVIulHF1eGDBo5QiMj6Zk9diCLh4k93nIjl5Lda83q2wLT0aedO3SVmKOtpmnDclRZtna/587crNzJnQv/+TnQMhhPiHFDiPIAWOyFNOnYLWrSEsTHvEevNmKFPmgc2Phkaz+HAoK4OuEZuYmm6do60RzyKFKF7YDkc7I2AgKTWNm/HJhMcmcishOV17o5WBZhXdeLFOSZ6r4YmdtfHBOWNitKelNm0Ca2v44w9tMk0hhMgmUuA8ghQ4Is85f14rcq5cAU9P7VHrevUeuklSahoHL0Wx42wEBy7d4nR4HEmpD5/uwcoA3sUcqe9dlKYV3WheyY1ihe0ene/SJWjfXivGHBxg8WJ47rmsHKEQQjySFDiPIAWOyJNCQ6FdOzh5Unvk+vffoVOnTG+emmbi8s3bRMQmEhGXRGJKGgqwNVpRrLAtxZ3sqFC8MPY2D7lKk5G1a7VH22/dgpIlteKrbt2s7UMIITJBCpxHkAJH5FkxMdC9O6xfr30/YgRMmKBN95DTkpNh7Fj46ivt+/r1YflyKFUq57MIIQqErHx+y0jGQuQlLi7aFZK7M5BPngxNm2pXdXJSUJA2Qejd4ubNN2H3biluhBC5hhQ4QuQ11tYwcaI2cF7RonDoENSpAx9/DImJln3vqCh46y2tuDl2DNzctP42P/wAdpnoqyOEEDlEChwh8qqOHbUio0MH7fHszz7TnrKaPRtSUx+9fVbEx8O332r7nzxZ23+nTtqVo86ds/e9hBAiG0iBI0ReVrq0diVn0SLt66tXtXFnKleG776D6Ogn2/+FC/Dhh+DtDe+8AzdvQtWqsGGDNiN4iRLZchhCCJHdpJOxdDIW+cWdOzB9ujYj+a1/BvuztdXmtXrpJXjqKahQQRuA70FSUuDECa2AWbNG61dzV6VKMHo09O6t3SYTQogclmueooqKimLYsGGsXLkSgI4dOzJ16lSKFCny4EAP+OX79ddf88477wDQsmVLduzYkW59t27dWLBgQaZySYEj8rXbt7XZyKdOhePH069zc9MKFW9vrcOytbU2ueeNG9pj6CdPat/fZTBoBdKAAVqRZMziI+RCCJGNck2B065dO65evcqMGTMAeP311ylbtiyrVq164Dbh4eHpvl+3bh39+/fn/PnzlC9fHtAKnMqVK/Ppp5+a2xUqVAgXF5dM5ZICRxQISmkFy5Il2hWZw4e1R7sfxclJu9rTrp3Wz+eemcyFEEIvWfn8tth15uDgYNavX8++ffto1KgRADNnzsTPz48zZ87g4+OT4XYe98yzs2LFCp5++mlzcXOXg4PDfW2FEP9hMED16tpr7Fjtyszx43D5sjaBZ3y81lnYxkbrS+Phoc13VbYsWEn3PCFE3maxAicgIAAXFxdzcQPQuHFjXFxc2Lt37wMLnP+6fv06a9asYe7cufetmzdvHn/88Qfu7u60a9eOsWPH4uTklK3HIES+YmenDcZXv77eSYQQwuIsVuCEh4dTIoMnLEqUKHHfbagHmTt3Lk5OTrz88svplvfo0YNy5crh4eHBiRMnGDNmDEePHmXTpk0Z7icpKYmk//QriI2NzbCdEEIIIfKHLF+HHjduHAaD4aGvQ4cOARl3GFZKPbAj8b1mz55Njx49sLe3T7d84MCBtG7dmurVq9O9e3f++usvNm/ezJEjRzLcz/jx43FxcTG/vKRPgRBCCJGvZfkKzpAhQ+jevftD25QtW5Zjx45x/fr1+9bduHEDd3f3R77Prl27OHPmDAsXLnxk27p162JjY8O5c+eom8Ekf2PGjGHk3aHt0a7gSJEjhBBC5F9ZLnDc3Nxwc3N7ZDs/Pz9iYmI4cOAADRs2BGD//v3ExMTQpEmTR24/a9Ys6tWrR61atR7Z9uTJk6SkpODp6Znhejs7O+xkGHkhhBCiwLDYoxK+vr60bduWgQMHsm/fPvbt28fAgQNp3759ug7GVapUYdmyZem2jY2NZfHixQwYMOC+/V64cIFPP/2UQ4cOcfnyZdauXUuXLl2oU6cOTZs2tdThCCGEECIPseizoPPmzaNGjRr4+/vj7+9PzZo1+f3339O1OXPmDDExMemWLViwAKUUr7zyyn37tLW1ZcuWLbRp0wYfHx+GDRuGv78/mzdvxiiDkAkhhBACmapBBvoTQggh8oisfH7LaF5CCCGEyHekwBFCCCFEviMFjhBCCCHyHSlwhBBCCJHvSIEjhBBCiHxHChwhhBBC5DsWm2wzN7v7ZLxMuimEEELkHXc/tzMzwk2BLHDi4uIAZD4qIYQQIg+Ki4vDxcXloW0K5EB/JpOJa9eu4eTklOmZzTPr7kSeoaGhMoigBcl5zhlynnOGnOecI+c6Z1jqPCuliIuLo2TJklhZPbyXTYG8gmNlZUXp0qUt+h7Ozs7yP08OkPOcM+Q85ww5zzlHznXOsMR5ftSVm7ukk7EQQggh8h0pcIQQQgiR70iBk83s7OwYO3YsdnZ2ekfJ1+Q85ww5zzlDznPOkXOdM3LDeS6QnYyFEEIIkb/JFRwhhBBC5DtS4AghhBAi35ECRwghhBD5jhQ4QgghhMh3pMB5DNOnT6dcuXLY29tTr149du3a9dD2O3bsoF69etjb21O+fHl++umnHEqat2XlPC9dupRnn32W4sWL4+zsjJ+fHxs2bMjBtHlXVn+e79qzZw/W1tbUrl3bsgHziaye56SkJD744AO8vb2xs7OjQoUKzJ49O4fS5l1ZPc/z5s2jVq1aODg44OnpSb9+/bh582YOpc2bdu7cSYcOHShZsiQGg4Hly5c/chtdPgeVyJIFCxYoGxsbNXPmTHXq1Ck1fPhw5ejoqK5cuZJh+4sXLyoHBwc1fPhwderUKTVz5kxlY2Oj/vrrrxxOnrdk9TwPHz5cTZgwQR04cECdPXtWjRkzRtnY2KgjR47kcPK8Javn+a7o6GhVvnx55e/vr2rVqpUzYfOwxznPHTt2VI0aNVKbNm1Sly5dUvv371d79uzJwdR5T1bP865du5SVlZWaMmWKunjxotq1a5eqVq2aevHFF3M4ed6ydu1a9cEHH6glS5YoQC1btuyh7fX6HJQCJ4saNmyoBg0alG5ZlSpV1OjRozNs/+6776oqVaqkW/a///1PNW7c2GIZ84OsnueMVK1aVX3yySfZHS1fedzz3K1bN/Xhhx+qsWPHSoGTCVk9z+vWrVMuLi7q5s2bOREv38jqef7mm29U+fLl0y37/vvvVenSpS2WMb/JTIGj1+eg3KLKguTkZA4fPoy/v3+65f7+/uzduzfDbQICAu5r36ZNGw4dOkRKSorFsuZlj3Oe72UymYiLi8PV1dUSEfOFxz3Pc+bM4cKFC4wdO9bSEfOFxznPK1eupH79+nz99deUKlWKypUrM2rUKO7cuZMTkfOkxznPTZo04erVq6xduxalFNevX+evv/7i+eefz4nIBYZen4MFcrLNxxUZGUlaWhru7u7plru7uxMeHp7hNuHh4Rm2T01NJTIyEk9PT4vlzase5zzfa+LEiSQkJNC1a1dLRMwXHuc8nzt3jtGjR7Nr1y6sreXXR2Y8znm+ePEiu3fvxt7enmXLlhEZGcngwYO5deuW9MN5gMc5z02aNGHevHl069aNxMREUlNT6dixI1OnTs2JyAWGXp+DcgXnMRgMhnTfK6XuW/ao9hktF+ll9TzfNX/+fMaNG8fChQspUaKEpeLlG5k9z2lpabz66qt88sknVK5cOafi5RtZ+Xk2mUwYDAbmzZtHw4YNee655/juu+/49ddf5SrOI2TlPJ86dYphw4bx8ccfc/jwYdavX8+lS5cYNGhQTkQtUPT4HJQ/wbLAzc0No9F4318DERER91Wnd3l4eGTY3trammLFilksa172OOf5roULF9K/f38WL15M69atLRkzz8vqeY6Li+PQoUMEBgYyZMgQQPsgVkphbW3Nxo0beeaZZ3Ike17yOD/Pnp6elCpVChcXF/MyX19flFJcvXqVSpUqWTRzXvQ453n8+PE0bdqUd955B4CaNWvi6OhI8+bN+fzzz+UKezbR63NQruBkga2tLfXq1WPTpk3plm/atIkmTZpkuI2fn9997Tdu3Ej9+vWxsbGxWNa87HHOM2hXbvr27cuff/4p99AzIavn2dnZmePHjxMUFGR+DRo0CB8fH4KCgmjUqFFORc9THufnuWnTply7do34+HjzsrNnz2JlZUXp0qUtmjevepzzfPv2bays0n8MGo1G4N8rDOLJ6fY5aNEuzPnQ3ccQZ82apU6dOqVGjBihHB0d1eXLl5VSSo0ePVr16tXL3P7u43FvvfWWOnXqlJo1a5Y8Jp4JWT3Pf/75p7K2tlbTpk1TYWFh5ld0dLReh5AnZPU830ueosqcrJ7nuLg4Vbp0adW5c2d18uRJtWPHDlWpUiU1YMAAvQ4hT8jqeZ4zZ46ytrZW06dPVxcuXFC7d+9W9evXVw0bNtTrEPKEuLg4FRgYqAIDAxWgvvvuOxUYGGh+HD+3fA5KgfMYpk2bpry9vZWtra2qW7eu2rFjh3ldnz59VIsWLdK13759u6pTp46ytbVVZcuWVT/++GMOJ86bsnKeW7RooYD7Xn369Mn54HlMVn+e/0sKnMzL6nkODg5WrVu3VoUKFVKlS5dWI0eOVLdv387h1HlPVs/z999/r6pWraoKFSqkPD09VY8ePdTVq1dzOHXesm3btof+vs0tn4MGpeQ6nBBCCCHyF+mDI4QQQoh8RwocIYQQQuQ7UuAIIYQQIt+RAkcIIYQQ+Y4UOEIIIYTId6TAEUIIIUS+IwWOEEIIIfIdKXCEEEIIke9IgSOEEEKIfEcKHCGEEELkO1LgCCGEECLfkQJHCCGEEPnO/wGGJUcfiAb0WQAAAABJRU5ErkJggg==",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "X = np.linspace(range_min, range_max, 200)\n",
+ "\n",
+ "# Change the plot size\n",
+ "default_figsize = mpl.rcParamsDefault['figure.figsize']\n",
+ "mpl.rcParams['figure.figsize'] = [1 * value for value in default_figsize]\n",
+ "\n",
+ "plot_solution(m, N, X, res.x, lambda_random)\n",
+ "\n",
+ "plt.plot(X, u(X), 'r', label='Analytical solution')\n",
+ "plt.legend()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "82740227",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Loss function value')"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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dqrIcHl2sELyH0GIiIiIDHyMkK4Y4xghgLvQExER/RWDUAuMcdYY8OcUerYIERERNWAQMiHq1aW5lhAREREABqEWGXvXWA67xoiIiAAwCLXI2LvGsoqr/nYAOhERkSlgEDIh7vaWEASgpl6FoopaqcshIiKSHIOQCbEwk8HVtmFT2ZwSdo8RERExCJkYz9u6x4iIiEwdg1ALjHWwNAB4cvNVIiIiNQahFhjrYGkA8HTgWkJERESNGIRMjHp1aY4RIiIiYhAyNewaIyIi+hODkInx5DYbREREagxCLTDuwdINQSivrAZ1SpXE1RAREUnrnoJQdbVxjjMx5sHSzjYWsDCTQRSBXI4TIiIiE6dxEFKpVHj77bfRqVMn2Nra4saNGwCAN954A5988onWCyTtEgQBng4cJ0RERATcRRB65513sHXrVqxevRoWFhbq48HBwfj444+1WhzphnrzVbYIERGRidM4CH3xxRfYsmULnn76acjlcvXxkJAQXLlyRavFkW5wdWkiIqIGGgehrKwsdO3atdlxlUqFuro6rRRFusWuMSIiogYaB6FevXrhyJEjzY5/99136N27t1aKIt1i1xgREVEDM01/YNmyZZg6dSqysrKgUqmwY8cOJCUl4YsvvsBPP/2kixrbXXR0NKKjo6FUKqUuRSe4lhAREVEDjVuExo4di+3bt+Pnn3+GIAh48803cfnyZfz4448YMWKELmpsd8Y8fR74c3VpjhEiIiJTp3GLEACMGjUKo0aN0nYt1E48/th4tay6HmXVdbCzNJe4IiIiImlwZWkTZKMwQwfrhvDDcUJERGTKNA5CMpkMcrn8jg8yDL5O1gCAY9cKJK6EiIhIOhp3je3cubPJ87q6Opw9exaff/453nrrLa0VRrr1eIQ3zmWW4OMjKXimny/M5WwcJCIi0yOIoihq40Jff/01tm/fjh9++EEbl9MLpaWlcHBwQElJCezt7aUuR6uq65QYtOo3FJTX4r9PhWF8WCepSyIiItIKTb6/tdYMEBkZif3792vrcqRjluZyTB/gBwD44NANaCkPExERGRStBKGqqiq8//778PLy0sblqJ08088X1hZyXM4pxeGrHCtERESmR+MxQo6OjhAEQf1cFEWUlZXB2toaX375pVaLI93qYG2Byff54JOjKfgg9jru7+4qdUlERETtSuMgtG7duiZB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ralUKowdOxarVq1qdk7jFz8A2NjY/O01b79uI1EUNZoh11j7nj170KlTpyavKRSKNr9/S+97+5+xlZVVm+q5/c/39j8zoGFs15QpU7Bnzx788ssvWLZsGbZt24aJEye26dpExowtQkTUzMqVK/Hjjz8iLi6uyXFXV1fk5uY2+aLW5to/x48fV/93fX094uPj1a0+ffr0waVLl+Dn54euXbs2ebQ1/ACAvb09PD09cfTo0SbH4+LiEBAQ0ObrBAYGQqFQID09vVk93t7ed/xct27dQnJysvpzBQYGtlhL9+7dIZfLERwcDJVK1Wzckaa6d++OBQsWYN++fZg0aRI+++yze7oekbFgixARNRMcHIynn34a77//fpPjQ4cORX5+PlavXo3HHnsMe/fuxS+//AJ7e3utvG90dDS6deuGgIAArFu3Drdu3VIP+p09ezY++ugjTJ48GUuWLIGLiwuuXbuGbdu24aOPPoJcLm/z+yxZsgTLli1Dly5dEBYWhs8++wwJCQn46quv2nwNOzs7LF68GAsWLIBKpcKgQYNQWlqKuLg42NraYtq0aepzV6xYAWdnZ7i7u2Pp0qVwcXHBhAkTAACLFi1C37598fbbb+PJJ5/E77//jo0bN2LTpk0AAD8/P0ybNg3PPfccNmzYgNDQUKSlpSEvL6/ZQPGWVFVVYcmSJXjsscfg7++PzMxMnDp1Co8++mibPyuRMWOLEBG16O23327WDRYQEIBNmzYhOjoaoaGhOHny5B1nVN2NlStXYtWqVQgNDcWRI0fwww8/wMXFBQDg6emJY8eOQalUYtSoUQgKCsK8efPg4ODQZDxSW8ydOxeLFi3CokWLEBwcjL1792L37t3o1q2bRtd5++238eabbyIqKgoBAQEYNWoUfvzxR/j7+zf7XPPmzUN4eDhycnKwe/duWFhYAGho6fr222+xbds2BAUF4c0338SKFSuadEtu3rwZjz32GF588UX07NkTzz//PCoqKtpUo1wuR2FhIZ599ll0794dTzzxBEaPHo233npLo89KZKwE8a9/0xERkVbExsZi2LBhuHXrFjp06CB1OUTUArYIERERkcliECIiIiKTxa4xIiIiMllsESIiIiKTxSBEREREJotBiIiIiEwWgxARERGZLAYhIiIiMlkMQkRERGSyGISIiIjIZDEIERERkcn6/2FBqce4m0I2AAAAAElFTkSuQmCC",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plt.plot([v[0] for v in loss_evolution])\n",
+ "plt.yscale(\"log\")\n",
+ "plt.xlabel(\"Number of epochs\")\n",
+ "plt.ylabel(\"Loss function value\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "6fdb8bee",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: repeat the computation with 5 photons and 3 photons. Can you notice the change in graphs?\n",
+ "# Why does the accuracy of our solution depend on the amount of photons we use?"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3541e471",
+ "metadata": {},
+ "source": [
+ "## References\n",
+ "\n",
+ "> [1] O. Kyriienko, A. E. Paine, and V. E. Elfving, “Solving nonlinear differential equations with differentiable quantum circuits”, [Physical Review A](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.103.052416) **103**, 052416 (2021).\n",
+ "\n",
+ "> [2] A. Pérez-Salinas, A. Cervera-Lierta, E. Gil-Fuster, and J. I. Latorre, “Data re-uploading for a universal quantum classifier”, [Quantum](https://quantum-journal.org/papers/q-2020-02-06-226/) **4**, 226 (2020).\n",
+ "\n",
+ "> [3] M. Schuld, R. Sweke, and J. J. Meyer, “Effect of data encoding on the expressive power of variational quantum-machine-learning models”, [Physical Review A]( https://journals.aps.org/pra/abstract/10.1103/PhysRevA.103.032430) **103**, 032430 (2021).\n",
+ "\n",
+ "> [4] B. Y. Gan, D. Leykam, D. G. Angelakis, and D. G. Angelakis, “Fock State-enhanced Expressivity of Quantum Machine Learning Models”, in [Conference on Lasers andElectro-Optics](https://opg.optica.org/abstract.cfm?uri=CLEO_AT-2021-JW1A.73) (2021), paper JW1A.73. Optica Publishing Group, (2021).\n",
+ "\n",
+ "> [5] R. Fletcher, Practical methods of optimization. [John Wiley & Sons](https://onlinelibrary.wiley.com/doi/book/10.1002/9781118723203). (2013)."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Differential_equation_resolution_answers.ipynb b/Differential_equation_resolution_answers.ipynb
new file mode 100644
index 0000000..08f4b9d
--- /dev/null
+++ b/Differential_equation_resolution_answers.ipynb
@@ -0,0 +1,643 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "1c11286e",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b0c92f7",
+ "metadata": {},
+ "source": [
+ "### Differential equation resolution"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a74dd31d",
+ "metadata": {},
+ "source": [
+ "Differential equations are used to describe variables that continuously vary with respect to a change in other variables. These equations can be used to model the behaviours of complex systems. A simple example of this can be found in economics, where we wish to study the relationships between some variables and predict their future behaviours."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "5726700a",
+ "metadata": {},
+ "source": [
+ "#### Introduction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e67d9ab4",
+ "metadata": {},
+ "source": [
+ "We present here a Perceval implementation of a Quantum Machine Learning algorithm for solving differential equations. Its aim is to approximate the solution to the differential equation considered in [1]:\n",
+ "\n",
+ "$$\\frac{df}{dx}+\\lambda f(x)(\\kappa+tan(\\lambda x))=0$$\n",
+ "\n",
+ "with boundary condition $f(0)=f_0$. The analytical solution is $f(x)=f_0\\;exp(-\\kappa \\lambda x) cos(\\lambda x)$."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f5b00399",
+ "metadata": {},
+ "source": [
+ "#### QML loss function definition"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c47833b5",
+ "metadata": {},
+ "source": [
+ "In order to use QML to solve this differential equation, we first need to derive a loss function from it whose minimum is associated to the differential equation's analytical solution.\n",
+ "\n",
+ "Let $F[\\{d^mf/dx^m\\}_m,f,x]=0$ be a general differential equation verified by $f(x)$, where $F[.]$ is an operator acting on $f(x)$, its derivatives and $x$. For the solving of a differential equation, the loss function described in [1] consists of two terms $$\\mathcal{L}_{\\theta}[\\{d^mg/dx^m\\}_m,g,x]=\\mathcal{L}_{\\theta}^{(diff)}[\\{d^mg/dx^m\\}_m,g,x]+\\mathcal{L}_{\\theta}^{(boundary)}[g,x].$$\n",
+ "\n",
+ "The first term $\\mathcal{L}_{\\theta}^{(diff)}$ corresponds to the differential equation which has been discretised over a fixed regular grid of M points noted $x_i$: $$\\mathcal{L}_{\\theta}^{(diff)}[\\{d^mg/dx^m\\}_m,g,x]=\\frac{1}{M}\\sum_{i=1}^{M}L(F[d_x^mg(x_i),g(x_i),x_i],0),$$\n",
+ "\n",
+ "where $L(a,b)=(a-b)^2$ is the squared distance between two arguments. The second term $\\mathcal{L}_{\\theta}^{(boundary)}$ is associated with the initial conditions of our desired solution. It is defined as: $$\\mathcal{L}_{\\theta}^{(boundary)}[g,x]=\\eta L(g(x_0),f_0),$$\n",
+ "\n",
+ "where $\\eta$ is the weight granted to the boundary condition and $f_0$ is given by $f(x_0)=f_0$.\n",
+ "\n",
+ "Given a function approximator $f^{(n)}(x,\\pmb{\\theta},\\pmb{\\lambda})$, the loss function above will be minimised using a classical algorithm, updating the parameters $\\pmb{\\theta}$ based on samples obtained using a quantum device."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3f075260",
+ "metadata": {},
+ "source": [
+ "#### Quantum circuit architecture"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "52b0ae69",
+ "metadata": {},
+ "source": [
+ "The feature map used is presented in [2,3,4]. The quantum circuit architecture from [4] is expressed as $\\mathcal{U}(x,\\pmb{\\theta})=\\mathcal{W}^{(2)}(\\pmb{\\theta}_2)\\mathcal{S}(x)\\mathcal{W}^{(1)}(\\pmb{\\theta}_1)$. The phase-shift operator $\\mathcal{S}(x)$ incorporates the $x$ dependency of the function we wish to approximate. It is sandwiched between two universal interferometers $\\mathcal{W}^{(1)}(\\pmb{\\theta}_1)$ and $\\mathcal{W}^{(2)}(\\pmb{\\theta}_2)$, where the beam splitter parameters $\\pmb{\\theta}_1$ and $\\pmb{\\theta}_2$ of this mesh architecture are tunable to enable training of the circuit. The output measurement operator, noted $\\mathcal{M}(\\pmb{\\lambda})$ is the projection on the Fock states obtained using photon-number resolving detectors, multiplied by some coefficients $\\pmb{\\lambda}$ which can also be tunable. Formally, we have:\n",
+ "\n",
+ "$$ \\mathcal{M}(\\boldsymbol{\\lambda}) = \\sum_{\\mathbf{\\left | n^{(f)}\\right \\rangle}}\\lambda_{\\mathbf{\\left | n^{(f)}\\right \\rangle}}\\mathbf{\\left | n^{(f)}\\right \\rangle}\\mathbf{\\left \\langle n^{(f)}\\right |},\n",
+ "$$\n",
+ "\n",
+ "where the sum is taken over all $\\binom{n+m-1}{n}$ possible Fock states considering $n$ photons in $m$ modes. Let $\\mathbf{\\left | n^{(i)}\\right \\rangle} = \\left |n^{(i)}_1,n^{(i)}_2,\\dots,n^{(i)}_m\\right \\rangle$ be the input state consisting of $n$ photons where $n^{(i)}_j$ is the number of photons in input mode $j$. Given these elements, the circuit's output $f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})$ is given by the following expectation value:\n",
+ "\n",
+ "$$\n",
+ "f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})=\\left\\langle\\mathbf{n}^{(i)}\\left|\\mathcal{U}^{\\dagger}(x, \\boldsymbol{\\theta}) \\mathcal{M}(\\boldsymbol{\\lambda}) \\mathcal{U}(x, \\boldsymbol{\\theta})\\right| \\mathbf{n}^{(i)}\\right\\rangle.\n",
+ "$$\n",
+ "\n",
+ "This expression can be rewritten as the following Fourier series \\[4\\]\n",
+ "\n",
+ "$$\n",
+ "f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})=\\sum_{\\omega \\in \\Omega_{n}} c_{\\omega}(\\boldsymbol{\\theta}, \\boldsymbol{\\lambda}) e^{i \\omega x},\n",
+ "$$\n",
+ "\n",
+ "where $\\Omega_n = \\{-n, -n+1, \\dots, n-1, n \\}$ is the frequency spectrum one can reach with $n$ incoming photons and $\\{c_\\omega(\\boldsymbol{\\theta}, \\boldsymbol{\\lambda})\\}$ are the Fourier coefficients. The $\\boldsymbol{\\lambda}$ parameters are sampled randomly in the interval $[-a;a]$, with $a$ a randomly chosen integer. $f^{(n)}(x, \\boldsymbol{\\theta}, \\boldsymbol{\\lambda})$ will serve as a function approximator for this chosen differential equation. Differentiation in the loss function is discretised as $\\frac{df}{dx} \\simeq \\frac{f(x+\\Delta x) - f(x-\\Delta x)}{2\\Delta x}$.\n",
+ "\n",
+ "$n, m,$ and $\\boldsymbol{\\lambda}$ are variable parameters defined below. $\\Delta x$ is the mesh size."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "664403cb",
+ "metadata": {},
+ "source": [
+ "## Perceval Simulation\n",
+ "\n",
+ "### Initialisation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "cb1aca2a",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import perceval as pcvl\n",
+ "import numpy as np\n",
+ "from math import comb\n",
+ "from scipy.optimize import minimize\n",
+ "import time\n",
+ "import matplotlib.pyplot as plt\n",
+ "import matplotlib as mpl\n",
+ "import tqdm as tqdm"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7b966a90",
+ "metadata": {},
+ "source": [
+ "We will run this notebook with 4 photons. We could use more photons, but the result with 4 photons is already satisfying."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "83c1de63",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "nphotons = 4"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "77763a57",
+ "metadata": {},
+ "source": [
+ "### Differential equation parameters\n",
+ "\n",
+ "We define here the value of the differential equation parameters and boundary condition $\\lambda, \\kappa, f_0$."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "266fa65b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Differential equation parameters\n",
+ "lambd = 8\n",
+ "kappa = 0.1\n",
+ "\n",
+ "def F(u_prime, u, x): # DE, works with numpy arrays\n",
+ " return u_prime + lambd * u * (kappa + np.tan(lambd * x))\n",
+ "\n",
+ "# Boundary condition (f(x_0)=f_0)\n",
+ "x_0 = 0\n",
+ "f_0 = 1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "057a3ae0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Modeling parameters\n",
+ "n_grid = 50 # number of grid points of the discretized differential equation\n",
+ "range_min = 0 # minimum of the interval on which we wish to approximate our function\n",
+ "range_max = 1 # maximum of the interval on which we wish to approximate our function\n",
+ "X = np.linspace(range_min, range_max-range_min, n_grid) # Optimisation grid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "d6aaeb2b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Differential equation's exact solution - for comparison\n",
+ "def u(x):\n",
+ " return np.exp(- kappa*lambd*x)*np.cos(lambd*x)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "6a4c54ba",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Parameters of the quantum machine learning procedure\n",
+ "N = nphotons # Number of photons\n",
+ "m = nphotons # Number of modes\n",
+ "eta = 5 # weight granted to the initial condition\n",
+ "a = 200 # Approximate boundaries of the interval that the image of the trial function can cover\n",
+ "fock_dim = comb(N + m - 1, N)\n",
+ "# lambda coefficients for all the possible outputs\n",
+ "lambda_random = 2 * a * np.random.rand(fock_dim) - a\n",
+ "# dx serves for the numerical differentiation of f\n",
+ "dx = (range_max-range_min) / (n_grid - 1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "662ad59e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "|1,1,1,1>\n"
+ ]
+ }
+ ],
+ "source": [
+ "# Input state with N photons and m modes\n",
+ "input_state = pcvl.BasicState([1]*N+[0]*(m-N))\n",
+ "print(input_state)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8b94a785",
+ "metadata": {},
+ "source": [
+ "## Definition of the circuit\n",
+ "\n",
+ "We will generate a Haar-random initial unitary using QR decomposition built in Perceval `Matrix.random_unitary`, the circuit is defined by the combination of 3 sub-circuits - the intermediate phase is a parameter."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "b90ce704",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "\"Haar unitary parameters\"\n",
+ "# number of parameters used for the two universal interferometers (2*m**2 per interferometer)\n",
+ "parameters = np.random.normal(size=4*m**2)\n",
+ "\n",
+ "px = pcvl.P(\"px\")\n",
+ "c = pcvl.Unitary(pcvl.Matrix.random_unitary(m, parameters[:2 * m ** 2]), name=\"W1\")\\\n",
+ " // (0, pcvl.PS(px))\\\n",
+ " // pcvl.Unitary(pcvl.Matrix.random_unitary(m, parameters[2 * m ** 2:]), name=\"W2\")\n",
+ "\n",
+ "backend = pcvl.BackendFactory().get_backend(\"SLOS\")\n",
+ "backend.set_circuit(pcvl.Unitary(pcvl.Matrix.random_unitary(m)))\n",
+ "backend.preprocess([input_state])\n",
+ "\n",
+ "pcvl.pdisplay(c)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "79b7fef9",
+ "metadata": {},
+ "source": [
+ "### Expectation value and loss function computation\n",
+ "\n",
+ "The expectation value of the measurement operator $\\mathcal{M}(\\boldsymbol{\\lambda})$ is obtained directly from Fock state probabilities computed by Perceval. Given this expectation value, the code snippet below computes the loss function defined in the Introduction.\n",
+ "\n",
+ "Note the use of the `all_prob` simulator method giving directly access to the probabilities of all possible output states, including null probabilities (probabilities of observing the state with m modes and 0 photons as all photons were lost). This calculation is optimized in the SLOS backend."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "27aa9449",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def computation(params):\n",
+ " global current_loss\n",
+ " global computation_count\n",
+ " \"compute the loss function of a given differential equation in order for it to be optimized\"\n",
+ " computation_count += 1\n",
+ " f_theta_0 = 0 # boundary condition\n",
+ " coefs = lambda_random # coefficients of the M observable\n",
+ " # initial condition with the two universal interferometers and the phase shift in the middle\n",
+ " U_1 = pcvl.Matrix.random_unitary(m, params[:2 * m ** 2])\n",
+ " U_2 = pcvl.Matrix.random_unitary(m, params[2 * m ** 2:])\n",
+ "\n",
+ " px = pcvl.P(\"x\")\n",
+ " c = pcvl.Unitary(U_2) // (0, pcvl.PS(px)) // pcvl.Unitary(U_1)\n",
+ "\n",
+ " px.set_value(np.pi * x_0)\n",
+ " backend.set_circuit(c)\n",
+ " f_theta_0 = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " # boundary condition given a weight eta\n",
+ " loss = eta * (f_theta_0 - f_0) ** 2 * len(X)\n",
+ "\n",
+ " # Y[0] is before the domain we are interested in (used for differentiation), x_0 is at Y[1]\n",
+ " Y = np.zeros(n_grid + 2)\n",
+ "\n",
+ " # x_0 is at the beginning of the domain, already calculated\n",
+ " Y[1] = f_theta_0\n",
+ "\n",
+ " px.set_value(np.pi * (range_min - dx))\n",
+ " backend.set_circuit(c)\n",
+ " Y[0] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ "\n",
+ " for i in range(1, n_grid):\n",
+ " x = X[i]\n",
+ " px.set_value(np.pi * x)\n",
+ " backend.set_circuit(c)\n",
+ " Y[i + 1] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " px.set_value(np.pi * (range_max + dx))\n",
+ " backend.set_circuit(c)\n",
+ " Y[n_grid + 1] = np.sum(np.multiply(backend.all_prob(input_state), coefs))\n",
+ "\n",
+ " # Differentiation\n",
+ " Y_prime = (Y[2:] - Y[:-2])/(2*dx)\n",
+ "\n",
+ " loss += np.sum((F(Y_prime, Y[1:-1], X))**2)\n",
+ "\n",
+ " current_loss = loss / len(X)\n",
+ " return current_loss"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ff86ccf8",
+ "metadata": {},
+ "source": [
+ "### Classical optimisation\n",
+ "\n",
+ "Finally the code below performs the optimisation procedure using the loss function defined in the previous section. To this end, we use a Broyden–Fletcher–Goldfarb–Shanno (BFGS) optimiser \\[5\\] from the SciPy library. Since we're performing the optimization classically, this is considered a hybrid quantum-classical algorithm."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "51ca61eb",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def callbackF(parameters):\n",
+ " \"\"\"callback function called by scipy.optimize.minimize allowing to monitor progress\"\"\"\n",
+ " global current_loss\n",
+ " global computation_count\n",
+ " global loss_evolution\n",
+ " global start_time\n",
+ " now = time.time()\n",
+ " pbar.set_description(\"M= %d Loss: %0.5f #computations: %d elapsed: %0.5f\" % \n",
+ " (m, current_loss, computation_count, now-start_time))\n",
+ " pbar.update(1)\n",
+ " loss_evolution.append((current_loss, now-start_time))\n",
+ " computation_count = 0\n",
+ " start_time = now"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "a8dd63fd",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "M= 4 Loss: 0.02469 #computations: 325 elapsed: 4.56400: : 85it [01:47, 2.53s/it] "
+ ]
+ }
+ ],
+ "source": [
+ "computation_count = 0\n",
+ "current_loss = 0\n",
+ "start_time = time.time()\n",
+ "loss_evolution = []\n",
+ "\n",
+ "pbar = tqdm.tqdm()\n",
+ "res = minimize(computation, parameters, callback=callbackF, method='BFGS', options={'gtol': 1E-2})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "57d69698",
+ "metadata": {},
+ "source": [
+ "After the optimisation procedure, the optimal unitary parameters (in `res.x`) can be used to determine the quantum circuit parameters (beam-splitter reflectivity and phase-shifter angles) for an experimental realisation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "12b6343c",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Unitary parameters [ 1.33891468 0.18671167 0.23294109 0.66027105 -0.90538747 -0.16478482\n",
+ " -1.79778695 0.27640065 -0.42235108 -0.42638238 -0.55720517 -0.50342402\n",
+ " 2.98759829 0.58048485 -0.05092819 1.36887037 0.76989739 -0.45710592\n",
+ " 0.60972939 -1.30593682 0.31607202 0.80690103 -0.07061116 1.74802391\n",
+ " -0.33214799 -0.10327618 -0.09204192 0.08248837 0.44292407 1.5847011\n",
+ " -0.15747674 0.20716982 -0.39656236 -2.52802577 -0.13810356 1.15592549\n",
+ " -0.41093697 1.05903189 1.11363313 0.92263739 -0.85430684 0.86256034\n",
+ " 1.14379369 0.29563571 0.94241894 -1.00363776 -0.4509711 -1.69484381\n",
+ " -0.90294638 0.76882232 0.54888516 -1.35142993 -0.25475156 -0.6617475\n",
+ " -0.62901547 -0.35290343 -0.48896483 -1.07626614 -0.93944671 -0.10220152\n",
+ " -0.51258919 0.07453675 -0.15409034 0.22112889]\n"
+ ]
+ }
+ ],
+ "source": [
+ "print(\"Unitary parameters\", res.x)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b5fc2804",
+ "metadata": {},
+ "source": [
+ "### Plotting the approximation\n",
+ "\n",
+ "We can now plot the result of our optimisation in order to compare the QML algorithm's output and the analytical solution of the differential equation."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "1e37ce40",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_solution(m, N, X, optim_params, lambda_random):\n",
+ " Y = []\n",
+ " U_1 = pcvl.Matrix.random_unitary(m, optim_params[:2 * m ** 2])\n",
+ " U_2 = pcvl.Matrix.random_unitary(m, optim_params[2 * m ** 2:])\n",
+ " px = pcvl.P(\"x\")\n",
+ " c = pcvl.Unitary(U_2) // (0, pcvl.PS(px)) // pcvl.Unitary(U_1)\n",
+ "\n",
+ " for x in X:\n",
+ " px.set_value(np.pi * x)\n",
+ " backend.set_circuit(c)\n",
+ " f_theta = np.sum(np.multiply(backend.all_prob(input_state), lambda_random))\n",
+ " Y.append(f_theta)\n",
+ " exact = u(X)\n",
+ " plt.plot(X, Y, label=\"Approximation with {} photons\".format(N))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "28a1d993",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "X = np.linspace(range_min, range_max, 200)\n",
+ "\n",
+ "# Change the plot size\n",
+ "default_figsize = mpl.rcParamsDefault['figure.figsize']\n",
+ "mpl.rcParams['figure.figsize'] = [1 * value for value in default_figsize]\n",
+ "\n",
+ "plot_solution(m, N, X, res.x, lambda_random)\n",
+ "\n",
+ "plt.plot(X, u(X), 'r', label='Analytical solution')\n",
+ "plt.legend()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "82740227",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Text(0, 0.5, 'Loss function value')"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "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dqrIcHl2sELyH0GIiIiIDHyMkK4Y4xghgLvQExER/RWDUAuMcdYY8OcUerYIERERNWAQMiHq1aW5lhAREREABqEWGXvXWA67xoiIiAAwCLXI2LvGsoqr/nYAOhERkSlgEDIh7vaWEASgpl6FoopaqcshIiKSHIOQCbEwk8HVtmFT2ZwSdo8RERExCJkYz9u6x4iIiEwdg1ALjHWwNAB4cvNVIiIiNQahFhjrYGkA8HTgWkJERESNGIRMjHp1aY4RIiIiYhAyNewaIyIi+hODkInx5DYbREREagxCLTDuwdINQSivrAZ1SpXE1RAREUnrnoJQdbVxjjMx5sHSzjYWsDCTQRSBXI4TIiIiE6dxEFKpVHj77bfRqVMn2Nra4saNGwCAN954A5988onWCyTtEgQBng4cJ0RERATcRRB65513sHXrVqxevRoWFhbq48HBwfj444+1WhzphnrzVbYIERGRidM4CH3xxRfYsmULnn76acjlcvXxkJAQXLlyRavFkW5wdWkiIqIGGgehrKwsdO3atdlxlUqFuro6rRRFusWuMSIiogYaB6FevXrhyJEjzY5/99136N27t1aKIt1i1xgREVEDM01/YNmyZZg6dSqysrKgUqmwY8cOJCUl4YsvvsBPP/2kixrbXXR0NKKjo6FUKqUuRSe4lhAREVEDjVuExo4di+3bt+Pnn3+GIAh48803cfnyZfz4448YMWKELmpsd8Y8fR74c3VpjhEiIiJTp3GLEACMGjUKo0aN0nYt1E48/th4tay6HmXVdbCzNJe4IiIiImlwZWkTZKMwQwfrhvDDcUJERGTKNA5CMpkMcrn8jg8yDL5O1gCAY9cKJK6EiIhIOhp3je3cubPJ87q6Opw9exaff/453nrrLa0VRrr1eIQ3zmWW4OMjKXimny/M5WwcJCIi0yOIoihq40Jff/01tm/fjh9++EEbl9MLpaWlcHBwQElJCezt7aUuR6uq65QYtOo3FJTX4r9PhWF8WCepSyIiItIKTb6/tdYMEBkZif3792vrcqRjluZyTB/gBwD44NANaCkPExERGRStBKGqqiq8//778PLy0sblqJ08088X1hZyXM4pxeGrHCtERESmR+MxQo6OjhAEQf1cFEWUlZXB2toaX375pVaLI93qYG2Byff54JOjKfgg9jru7+4qdUlERETtSuMgtG7duiZB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ralUKowdOxarVq1qdk7jFz8A2NjY/O01b79uI1EUNZoh11j7nj170KlTpyavKRSKNr9/S+97+5+xlZVVm+q5/c/39j8zoGFs15QpU7Bnzx788ssvWLZsGbZt24aJEye26dpExowtQkTUzMqVK/Hjjz8iLi6uyXFXV1fk5uY2+aLW5to/x48fV/93fX094uPj1a0+ffr0waVLl+Dn54euXbs2ebQ1/ACAvb09PD09cfTo0SbH4+LiEBAQ0ObrBAYGQqFQID09vVk93t7ed/xct27dQnJysvpzBQYGtlhL9+7dIZfLERwcDJVK1Wzckaa6d++OBQsWYN++fZg0aRI+++yze7oekbFgixARNRMcHIynn34a77//fpPjQ4cORX5+PlavXo3HHnsMe/fuxS+//AJ7e3utvG90dDS6deuGgIAArFu3Drdu3VIP+p09ezY++ugjTJ48GUuWLIGLiwuuXbuGbdu24aOPPoJcLm/z+yxZsgTLli1Dly5dEBYWhs8++wwJCQn46quv2nwNOzs7LF68GAsWLIBKpcKgQYNQWlqKuLg42NraYtq0aepzV6xYAWdnZ7i7u2Pp0qVwcXHBhAkTAACLFi1C37598fbbb+PJJ5/E77//jo0bN2LTpk0AAD8/P0ybNg3PPfccNmzYgNDQUKSlpSEvL6/ZQPGWVFVVYcmSJXjsscfg7++PzMxMnDp1Co8++mibPyuRMWOLEBG16O23327WDRYQEIBNmzYhOjoaoaGhOHny5B1nVN2NlStXYtWqVQgNDcWRI0fwww8/wMXFBQDg6emJY8eOQalUYtSoUQgKCsK8efPg4ODQZDxSW8ydOxeLFi3CokWLEBwcjL1792L37t3o1q2bRtd5++238eabbyIqKgoBAQEYNWoUfvzxR/j7+zf7XPPmzUN4eDhycnKwe/duWFhYAGho6fr222+xbds2BAUF4c0338SKFSuadEtu3rwZjz32GF588UX07NkTzz//PCoqKtpUo1wuR2FhIZ599ll0794dTzzxBEaPHo233npLo89KZKwE8a9/0xERkVbExsZi2LBhuHXrFjp06CB1OUTUArYIERERkcliECIiIiKTxa4xIiIiMllsESIiIiKTxSBEREREJotBiIiIiEwWgxARERGZLAYhIiIiMlkMQkRERGSyGISIiIjIZDEIERERkcn6/2FBqce4m0I2AAAAAElFTkSuQmCC",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plt.plot([v[0] for v in loss_evolution])\n",
+ "plt.yscale(\"log\")\n",
+ "plt.xlabel(\"Number of epochs\")\n",
+ "plt.ylabel(\"Loss function value\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "35848cc4",
+ "metadata": {},
+ "source": [
+ "Repeating the entire computation with 3 photons would damage the accuracy of our solution but with 5 photons the accuracy would improve (the first graph above would have the two lines closer to one another). We used 4 photons as the solution is already satisfying.\n",
+ "\n",
+ "Why is the accuracy lower with 3 photons? Lowering the amount of photons lowers the expressibility of our circuit, deeming our ability to find a good solution to the differential equation lower."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3541e471",
+ "metadata": {},
+ "source": [
+ "## References\n",
+ "\n",
+ "> [1] O. Kyriienko, A. E. Paine, and V. E. Elfving, “Solving nonlinear differential equations with differentiable quantum circuits”, [Physical Review A](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.103.052416) **103**, 052416 (2021).\n",
+ "\n",
+ "> [2] A. Pérez-Salinas, A. Cervera-Lierta, E. Gil-Fuster, and J. I. Latorre, “Data re-uploading for a universal quantum classifier”, [Quantum](https://quantum-journal.org/papers/q-2020-02-06-226/) **4**, 226 (2020).\n",
+ "\n",
+ "> [3] M. Schuld, R. Sweke, and J. J. Meyer, “Effect of data encoding on the expressive power of variational quantum-machine-learning models”, [Physical Review A]( https://journals.aps.org/pra/abstract/10.1103/PhysRevA.103.032430) **103**, 032430 (2021).\n",
+ "\n",
+ "> [4] B. Y. Gan, D. Leykam, D. G. Angelakis, and D. G. Angelakis, “Fock State-enhanced Expressivity of Quantum Machine Learning Models”, in [Conference on Lasers andElectro-Optics](https://opg.optica.org/abstract.cfm?uri=CLEO_AT-2021-JW1A.73) (2021), paper JW1A.73. Optica Publishing Group, (2021).\n",
+ "\n",
+ "> [5] R. Fletcher, Practical methods of optimization. [John Wiley & Sons](https://onlinelibrary.wiley.com/doi/book/10.1002/9781118723203). (2013)."
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/One-qubit_and_two-qubit_gates_TO_DO.ipynb b/One-qubit_and_two-qubit_gates_TO_DO.ipynb
new file mode 100644
index 0000000..385fd2f
--- /dev/null
+++ b/One-qubit_and_two-qubit_gates_TO_DO.ipynb
@@ -0,0 +1,831 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "a682dc1b",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2d8e0129",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import perceval as pcvl\n",
+ "from perceval.components.unitary_components import PERM,PS,BS\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4abe4fee",
+ "metadata": {},
+ "source": [
+ "### One and two-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "854d6776",
+ "metadata": {},
+ "source": [
+ "Below is a list of commonly used quantum gates that can easily be applied to optical quantum computing in Perceval. The list is split into two, for one-qubit and two-qubit gates.\n",
+ "\n",
+ "Before we start, a quick reminder that we use a dual-rail encoding. This means that we encode one physical qubit using 2 modes, where a photon found in one or the other mode represent the qubit's excited or ground state."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2e2158fb",
+ "metadata": {},
+ "source": [
+ "#### One-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29a27b3e",
+ "metadata": {},
+ "source": [
+ "One-qubit gates can be applied to quantum optical systems in Perceval in the form of beam splitters with different reflectivity angles, applied to 2 input modes, phase shifters or simple permutations."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "237a0279",
+ "metadata": {},
+ "source": [
+ "##### Pauli-X gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0ce83f80",
+ "metadata": {},
+ "source": [
+ "A Pauli-X gate or the NOT gate can be built by applying a permutation that swaps the two input modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "ab1b39ac",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: design the Pauli-X gate in Perceval and display it"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b9fdeb79",
+ "metadata": {},
+ "source": [
+ "To check this is correct, you can print the unitary matrix that drives the action of this beam splitter."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "a6031764",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "pcvl.pdisplay(Pauli_X.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d2f3d761",
+ "metadata": {},
+ "source": [
+ "##### Pauli-Y gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c8ae306e",
+ "metadata": {},
+ "source": [
+ "Similarly, for the Pauli-Y gate we can first apply the Pauli-X gate and then add phase shifters with phases $-\\frac{\\pi}{2}$ and $\\frac{\\pi}{2}$ on modes 0 and 1 respectively."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "f62be79b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Pauli_Y = PERM([1,0]) // (0,PS(-np.pi/2)) // (1,PS(np.pi/2))\n",
+ "pcvl.pdisplay(Pauli_Y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "baeced45",
+ "metadata": {},
+ "source": [
+ "We can again check the matrix of this unitary transformation to convince ourselves it works correctly."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "54210de0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: check the unitary"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fa0f830d",
+ "metadata": {},
+ "source": [
+ "##### Pauli-Z gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44400661",
+ "metadata": {},
+ "source": [
+ "To apply a Pauli-Z gate, we can note that it is a rotation on the Z axis with an angle of $\\pi$. We can build this gate in Perceval by applying a phase shifter with phase $\\pi$ on the second of the two modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "8338b147",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: design the Pauli-Z gate in Perceval and display it"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e4840d31",
+ "metadata": {},
+ "source": [
+ "And once again we can verify the action of this circuit by checking its unitary."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "d66cb5fe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: check the unitary"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ec2bb996",
+ "metadata": {},
+ "source": [
+ "##### Hadamard gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3cedd273",
+ "metadata": {},
+ "source": [
+ "Finally, we apply a Hadamard gate by using a beam splitter with a predefined reflectivity angle that ensures the action of a Hadamard gate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "63692ec7",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Hadamard = BS.H()\n",
+ "pcvl.pdisplay(Hadamard)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ea170bfe",
+ "metadata": {},
+ "source": [
+ "And we can print its unitary to check its action as well."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "e3b24ab3",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: check the unitary"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9188c1d4",
+ "metadata": {},
+ "source": [
+ "#### Two-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8c44eeb1",
+ "metadata": {},
+ "source": [
+ "##### CZ-gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14888fa0",
+ "metadata": {},
+ "source": [
+ "The CZ-gate is a two-qubit controlled-Z gate, meaning that the action of the Pauli-Z gate is performed on the target qubit if the control logical qubit is $|1\\rangle$.\n",
+ "\n",
+ "The controlled-Z gate and its full circuit decomposition can be found in the Perceval catalog. This circuit also requires the use of ancillas and heralded gates."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "id": "eb65193d",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "HERALDED CZ DOCUMENTATION\n",
+ "--------------------------\n",
+ "\n",
+ "CZ gate with 2 heralded modes\n",
+ "\n",
+ "Scientific article reference: https://arxiv.org/abs/quant-ph/0110144\n",
+ "\n",
+ "Schema:\n",
+ " ╭─────╮\n",
+ "ctrl (dual rail) ─────┤ ├───── ctrl (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " │ │\n",
+ "data (dual rail) ─────┤ ├───── data (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " ╰─────╯\n",
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from perceval.components import catalog\n",
+ "print(catalog['heralded cz'].doc)\n",
+ "heralded_cz = catalog['heralded cz'].as_processor().build()\n",
+ "\n",
+ "pcvl.pdisplay(heralded_cz, recursive=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ef6bc00f",
+ "metadata": {},
+ "source": [
+ "Note that there's another way that we can build the CZ-gate. You may have seen before that the following holds: $Z=HXH$. It can similarly be shown that one can build a CZ-gate by applying a CNOT-gate sandwiched between two Hadamard gates."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "9c2f97a7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: Use the previously defined Pauli-Z, Pauli-X and Hadamard gates to prove the claim that a Pauli-X gate sandwiched between two Hadamard gates\n",
+ "# has the same action as a Pauli-Z gate. Display their unitaries and convince yourself that this is true."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3edb4686",
+ "metadata": {},
+ "source": [
+ "##### CNOT-gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8eb49074",
+ "metadata": {},
+ "source": [
+ "A CNOT-gate (controlled-NOT gate) is a two-qubit gate where one qubit acts as a control and the other as a target. If the control logical qubit is $|1\\rangle$, the target qubit is flipped (the Pauli-X or NOT-gate is applied), otherwise no action is taken."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3bae9549",
+ "metadata": {},
+ "source": [
+ "Knill, Laflamme and Milburn famously showed that a CNOT circuit can be built in a photonic quantum setting simply by using ancillas (additional photons) in an optical circuit with linear optical components and measurement. This is an important result and can be used for generation of entanglement.\n",
+ "\n",
+ "You can find the full circuit decomposition in the Perceval catalog.\n",
+ "\n",
+ "Note that this circuit requires the use of heralded gates and ancillas. The ancillas are measured separately from the other photons in the circuit and their measurement is used to check whether a gate performed its action well. This gate is then referred to as a heralded gate. Its action needs to be checked because two-qubit gates in dual-rail encoding are probabilistic, and therefore have a probability to fail."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "cad8bbd1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "HERALDED CNOT DOCUMENTATION\n",
+ "----------------------------\n",
+ "\n",
+ "CNOT gate with 4 heralded modes\n",
+ "\n",
+ "Scientific article reference: https://doi.org/10.1073/pnas.1018839108\n",
+ "\n",
+ "Schema:\n",
+ " ╭─────╮\n",
+ "ctrl (dual rail) ─────┤ ├───── ctrl (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " │ │\n",
+ "data (dual rail) ─────┤ ├───── data (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " ╰─────╯\n",
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "print(catalog['heralded cnot'].doc)\n",
+ "heralded_cnot = catalog['heralded cnot'].as_processor().build()\n",
+ "\n",
+ "pcvl.pdisplay(heralded_cnot, recursive=True) # we set recursive=True to show the full set of linear optical components used to build this circuit"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f8a05954",
+ "metadata": {},
+ "source": [
+ "##### SWAP gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "444762bd",
+ "metadata": {},
+ "source": [
+ "A two-qubit SWAP gate swaps the two qubit wires qubits travel through. For example the state $|1,0\\rangle$ becomes $|0,1\\rangle$ after passing through a SWAP gate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "772f9af0",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#TO DO: create and display a two-qubit SWAP gate, keeping in mind the dual-rail encoding"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/One-qubit_and_two-qubit_gates_answers.ipynb b/One-qubit_and_two-qubit_gates_answers.ipynb
new file mode 100644
index 0000000..4792fed
--- /dev/null
+++ b/One-qubit_and_two-qubit_gates_answers.ipynb
@@ -0,0 +1,1023 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "a682dc1b",
+ "metadata": {},
+ "source": [
+ "# Quandela Training Seminar - Programming with Perceval"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "7917bf96",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import perceval as pcvl\n",
+ "from perceval.components.unitary_components import PERM,PS,BS\n",
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4abe4fee",
+ "metadata": {},
+ "source": [
+ "### One and two-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "854d6776",
+ "metadata": {},
+ "source": [
+ "Below is a list of commonly used quantum gates that can easily be applied to optical quantum computing in Perceval. The list is split into two, for one-qubit and two-qubit gates.\n",
+ "\n",
+ "Before we start, a quick reminder that we use a dual-rail encoding. This means that we encode one physical qubit using 2 modes, where a photon found in one or the other mode represent the qubit's excited or ground state."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2e2158fb",
+ "metadata": {},
+ "source": [
+ "#### One-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "29a27b3e",
+ "metadata": {},
+ "source": [
+ "One-qubit gates can be applied to quantum optical systems in Perceval in the form of beam splitters with different reflectivity angles, applied to 2 input modes, phase shifters or simple permutations."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "237a0279",
+ "metadata": {},
+ "source": [
+ "##### Pauli-X gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "0ce83f80",
+ "metadata": {},
+ "source": [
+ "A Pauli-X gate or the NOT gate can be built by applying a permutation that swaps the two input modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "ab1b39ac",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Pauli_X = PERM([1,0])\n",
+ "pcvl.pdisplay(Pauli_X)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b9fdeb79",
+ "metadata": {},
+ "source": [
+ "To check this is correct, you can print the unitary matrix that drives the action of this beam splitter."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "a6031764",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}0 & 1\\\\1 & 0\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "pcvl.pdisplay(Pauli_X.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d2f3d761",
+ "metadata": {},
+ "source": [
+ "##### Pauli-Y gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c8ae306e",
+ "metadata": {},
+ "source": [
+ "Similarly, for the Pauli-Y gate we can first apply the Pauli-X gate and then add phase shifters with phases $-\\frac{\\pi}{2}$ and $\\frac{\\pi}{2}$ on modes 0 and 1 respectively."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "f62be79b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Pauli_Y = PERM([1,0]) // (0,PS(-np.pi/2)) // (1,PS(np.pi/2))\n",
+ "pcvl.pdisplay(Pauli_Y)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "baeced45",
+ "metadata": {},
+ "source": [
+ "We can again check the matrix of this unitary transformation to convince ourselves it works correctly."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "54210de0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}0 & - i\\\\i & 0\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "pcvl.pdisplay(Pauli_Y.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "fa0f830d",
+ "metadata": {},
+ "source": [
+ "##### Pauli-Z gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "44400661",
+ "metadata": {},
+ "source": [
+ "To apply a Pauli-Z gate, we can note that it is a rotation on the Z axis with an angle of $\\pi$. We can build this gate in Perceval by applying a phase shifter with phase $\\pi$ on the second of the two modes."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "8338b147",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Pauli_Z=pcvl.Circuit(2) // (1,PS(phi=np.pi))\n",
+ "pcvl.pdisplay(Pauli_Z)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e4840d31",
+ "metadata": {},
+ "source": [
+ "And once again we can verify the action of this circuit by checking its unitary."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "d66cb5fe",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "pcvl.pdisplay(Pauli_Z.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ec2bb996",
+ "metadata": {},
+ "source": [
+ "##### Hadamard gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3cedd273",
+ "metadata": {},
+ "source": [
+ "Finally, we apply a Hadamard gate by using a beam splitter with a predefined reflectivity angle that ensures the action of a Hadamard gate."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "63692ec7",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Hadamard = BS.H()\n",
+ "pcvl.pdisplay(Hadamard)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ea170bfe",
+ "metadata": {},
+ "source": [
+ "And we can print its unitary to check its action as well."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "e3b24ab3",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}\\frac{\\sqrt{2}}{2} & \\frac{\\sqrt{2}}{2}\\\\\\frac{\\sqrt{2}}{2} & - \\frac{\\sqrt{2}}{2}\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "pcvl.pdisplay(Hadamard.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "9188c1d4",
+ "metadata": {},
+ "source": [
+ "#### Two-qubit gates"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8c44eeb1",
+ "metadata": {},
+ "source": [
+ "##### CZ-gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "14888fa0",
+ "metadata": {},
+ "source": [
+ "The CZ-gate is a two-qubit controlled-Z gate, meaning that the action of the Pauli-Z gate is performed on the target qubit if the control logical qubit is $|1\\rangle$.\n",
+ "\n",
+ "The controlled-Z gate and its full circuit decomposition can be found in the Perceval catalog. This circuit also requires the use of ancillas and heralded gates."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "5be59512",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "HERALDED CZ DOCUMENTATION\n",
+ "--------------------------\n",
+ "\n",
+ "CZ gate with 2 heralded modes\n",
+ "\n",
+ "Scientific article reference: https://arxiv.org/abs/quant-ph/0110144\n",
+ "\n",
+ "Schema:\n",
+ " ╭─────╮\n",
+ "ctrl (dual rail) ─────┤ ├───── ctrl (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " │ │\n",
+ "data (dual rail) ─────┤ ├───── data (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " ╰─────╯\n",
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from perceval.components import catalog\n",
+ "print(catalog['heralded cz'].doc)\n",
+ "heralded_cz = catalog['heralded cz'].as_processor().build()\n",
+ "\n",
+ "pcvl.pdisplay(heralded_cz, recursive=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8141ad80",
+ "metadata": {},
+ "source": [
+ "Notice the 2 ancillary heralded modes, each of which has an input photon. These are used in the outer beam splitters (left top and bottom) that balance detection probability, while the inner (top right beam splitter) creates interference between the two qubits encoded in dual-rail encoding."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ef6bc00f",
+ "metadata": {},
+ "source": [
+ "Note that there's another way that we can build the CZ-gate. You may have seen before that the following holds: $Z=HXH$. It can similarly be shown that one can build a CZ-gate by applying a CNOT-gate sandwiched between two Hadamard gates."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "id": "bb384b95",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "$\\left[\\begin{matrix}1 & 0\\\\0 & -1\\end{matrix}\\right]$"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# proving that Z=HXH holds, using the previously defined gates\n",
+ "HXH = Hadamard // Pauli_X // Hadamard\n",
+ "pcvl.pdisplay(HXH.compute_unitary())\n",
+ "pcvl.pdisplay(Pauli_Z.compute_unitary())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3edb4686",
+ "metadata": {},
+ "source": [
+ "##### CNOT-gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8eb49074",
+ "metadata": {},
+ "source": [
+ "A CNOT-gate (controlled-NOT gate) is a two-qubit gate where one qubit acts as a control and the other as a target. If the control logical qubit is $|1\\rangle$, the target qubit is flipped (the Pauli-X or NOT-gate is applied), otherwise no action is taken."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3bae9549",
+ "metadata": {},
+ "source": [
+ "Knill, Laflamme and Milburn famously showed that a CNOT circuit can be built in a photonic quantum setting simply by using ancillas (additional photons) in an optical circuit with linear optical components and measurement. This is an important result and can be used for generation of entanglement.\n",
+ "\n",
+ "You can find the full circuit decomposition in the Perceval catalog.\n",
+ "\n",
+ "Note that this circuit requires the use of heralded gates and ancillas. The ancillas are measured separately from the other photons in the circuit and their measurement is used to check whether a gate performed its action well. This gate is then referred to as a heralded gate. Its action needs to be checked because two-qubit gates in dual-rail encoding are probabilistic, and therefore have a probability to fail."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "cad8bbd1",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "HERALDED CNOT DOCUMENTATION\n",
+ "----------------------------\n",
+ "\n",
+ "CNOT gate with 4 heralded modes\n",
+ "\n",
+ "Scientific article reference: https://doi.org/10.1073/pnas.1018839108\n",
+ "\n",
+ "Schema:\n",
+ " ╭─────╮\n",
+ "ctrl (dual rail) ─────┤ ├───── ctrl (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " │ │\n",
+ "data (dual rail) ─────┤ ├───── data (dual rail)\n",
+ " ─────┤ ├─────\n",
+ " ╰─────╯\n",
+ "\n"
+ ]
+ },
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "print(catalog['heralded cnot'].doc)\n",
+ "heralded_cnot = catalog['heralded cnot'].as_processor().build()\n",
+ "\n",
+ "pcvl.pdisplay(heralded_cnot, recursive=True) # we set recursive=True to show the full set of linear optical components used to build this circuit"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "a8d2497f",
+ "metadata": {},
+ "source": [
+ "Note that there's another way that we can build the CNOT-gate. You may have seen before that the following holds: $X=HZH$. It can similarly be shown that one can build a CNOT-gate by applying a CZ-gate sandwiched between two Hadamard gates. Since the CZ-gate requires only 2 ancillary modes, here the CNOT gate would also require only 2."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f8a05954",
+ "metadata": {},
+ "source": [
+ "##### SWAP gate"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "444762bd",
+ "metadata": {},
+ "source": [
+ "A two-qubit SWAP gate swaps the two quantum wires qubits travel through. For example the state $|1,0\\rangle$ becomes $|0,1\\rangle$ after passing through a SWAP gate.\n",
+ "\n",
+ "In optical quantum computing, the SWAP gate can easily be applied by swapping modes, not forgetting that in our case a quantum wire is represented by two modes as we use dual-rail encoding."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "772f9af0",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "SWAP = PERM([2,3,0,1])\n",
+ "pcvl.pdisplay(SWAP)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.9"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}