{ "cells": [ { "cell_type": "markdown", "id": "6c48eed1a03dc991", "metadata": {}, "source": [ "# Representing partially dinstinguishable states" ] }, { "cell_type": "markdown", "id": "8dffc439586728bb", "metadata": {}, "source": [ "In this notebook, we use the different kinds of `BasicState` to present how the user can handle complex inputs using perceval." ] }, { "cell_type": "code", "execution_count": 1, "id": "e372a8863b8965ff", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "from perceval import BasicState, AnnotatedFockState, StateVector, Annotation" ] }, { "cell_type": "markdown", "id": "5df9f6df6986294d", "metadata": {}, "source": [ "## BasicState insight" ] }, { "cell_type": "markdown", "id": "84c4ba30e0915672", "metadata": {}, "source": [ "A `BasicState` is a class that embodies three different kinds of Fock states. The class init chooses the correct representation according to its arguments, and most methods are common to all the classes.\n", "\n", "- The `FockState` represents indistinguishable photons. The representation shows the number of photon in each mode (e.g. $|0, 1, 0, 2\\rangle$)\n", "- The `NoisyFockState` represents groups of indistinguishable photons, where each group is represented using an integer (the 'noise tag') from 0 to 255. The photons from different groups are totally distinguishable and do not interact at all. The representation shows the noise tag between brackets (e.g. $|0, \\{0\\}, 0, \\{0\\}\\{1\\}\\rangle$)\n", "- The `AnnotatedFockState` is a generic state class where photons can be given string tags associated with values. The representation shows the tag and the value separated by a semicolon, all between brackets (e.g. $|0, \\{P:0\\}, 0, \\{P:1.57\\}\\{P:3.14\\}\\rangle$).\n", "\n", "In the general case, it is not possible to simulate the results of an `AnnotatedFockState`.\n", "The user can provide a way to compute distinguishability from annotations comparison, which allows to handle some physical properties. Here we show an example of computations with photon wavelength, by converting an `AnnotatedFockState` into a superposition of `FockState` and `NoisyFockState`." ] }, { "cell_type": "markdown", "id": "d6a007889e9cd8b", "metadata": {}, "source": [ "## Example: wavelength\n", "\n", "Suppose you have two photons of different wavelength arriving at a perfect beam splitter. We want to study how a difference in wavelength will affect the HOM effect." ] }, { "cell_type": "code", "execution_count": 2, "id": "initial_id", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "|{wavelength:6.25e-07},{wavelength:6.15e-07}>\n" ] } ], "source": [ "# This creates two AnnotatedFockStates with an associated wavelength\n", "state_1 = BasicState(\"|{wavelength:625e-9}>\") # The first source produced state\n", "state_2 = BasicState(\"|{wavelength:615e-9}>\") # The second source produced state\n", "\n", "# The whole input state arriving at the chip is then\n", "input_state = state_1 * state_2\n", "print(input_state)" ] }, { "cell_type": "markdown", "id": "42647cee52df73e", "metadata": {}, "source": [ "The problem now is that perceval doesn't know how distinguishable are these photons. So, as a user, we first need to convert this to something that Perceval can simulate.\n", "\n", "For that, we introduce a model where the indistinguishability depends on the wavelength of the two photons." ] }, { "cell_type": "code", "execution_count": 3, "id": "6e3a20cceee955ff", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.999*|1,1>+0.032*|{0},{1}>\n" ] } ], "source": [ "def compute_indistinguishability(photon_1: Annotation, photon_2: Annotation):\n", " # To make sense, this method must at least verify:\n", " # - compute_indistinguishability(a, b) == compute_indistinguishability(b, a)\n", " # - compute_indistinguishability(a, a) == 1\n", " lambda_1 = photon_1[\"wavelength\"]\n", " lambda_2 = photon_2[\"wavelength\"]\n", " return np.exp(- 2 * (lambda_2 - lambda_1) ** 2 / (lambda_1 * lambda_2))\n", "\n", "def convert_state(state: AnnotatedFockState) -> StateVector:\n", " assert state.n == 2 # This method would fail otherwise\n", "\n", " photon1 = state.get_photon_annotation(0) # Get the annotation from the first photon\n", " photon2 = state.get_photon_annotation(1) # Get the annotation from the second photon\n", "\n", " indist = compute_indistinguishability(photon1, photon2)\n", "\n", " indist_state = state.clear_annotations() # This creates a FockState with photons at the same place\n", " # Same result than BasicState(list(state))\n", "\n", " noise = (1 - indist ** 2) ** 0.5 # So the final result is normalized\n", "\n", " noisy_state = BasicState(list(state), [0, 1]) # Creates a NoisyFockState with tags 0 and 1 so the two photons are distinguishable\n", "\n", " return indist_state * indist + noisy_state * noise # Creates a StateVector containing only state types that Perceval can simulate\n", "\n", "converted_input_state = convert_state(input_state)\n", "\n", "print(converted_input_state)" ] }, { "cell_type": "markdown", "id": "b802cc403ebce48d", "metadata": {}, "source": [ "We can now simulate using our state as usual." ] }, { "cell_type": "code", "execution_count": 4, "id": "d2fd16c1032d74e1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", "\t|0,2>: 0.4997399722916615\n", "\t|2,0>: 0.4997399722916615\n", "\t|1,1>: 0.0005200554166770454\n", "}\n" ] } ], "source": [ "from perceval import BS, Processor\n", "\n", "p = Processor(\"SLAP\", BS())\n", "p.min_detected_photons_filter(0)\n", "p.with_input(converted_input_state)\n", "\n", "print(p.probs()[\"results\"])" ] }, { "cell_type": "markdown", "id": "bf339ce618959ab5", "metadata": {}, "source": [ "Great! You now know how to create and use states defining (partially) distinguishable photons.\n", "Knowing how to use `BasicStates` that are more than just photon positions is a valuable tool for bigger and tougher problems, especially when state arithmetics is involved.\n", "\n", "The `AnnotatedFockState` can also be used to define polarization using the tag \"P\", that Perceval can natively handle, and that requires a more complex conversion (duplication of the circuit and state size, conversion back at the end...)" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }