`\n\n![](/tutorials/images/teleport.svg)\n\n :width: 60%\n :align: center\n :target: javascript:void(0);\n\n\n:html:`

`\n\nThis process can be explained as follows:\n\n1. Here, qumodes $q_1$ and $q_2$ are initially prepared as (the unphysical)\n infinitely squeezed vacuum states in momentum and position space respectively,\n\n .. math::\n &\\ket{0}_x \\sim \\lim_{z\\rightarrow\\infty} S(z)\\ket{0}\\\\ &\\ket{0}_p \\sim\n \\lim_{z\\rightarrow-\\infty} S(z)\\ket{0}=\\frac{1}{\\sqrt{\\pi}}\\int_{-\\infty}^\\infty \\ket{x}~dx\n\n before being maximally entangled by a 50-50 beamsplitter:\n\n .. math:: BS(\\pi/4,0)(\\ket{0}_p\\otimes\\ket{0}_x)\n\n\n2. These two qumodes are now spatially separated, with $\\ket{q_1}$ held by\n Alice, and $\\ket{q_2}$ held by Bob, with the two connected via the classical\n communication channels $c_0$ and $c_1$.\n\n\n3. To teleport her unknown state $\\ket{\\psi}$ to Bob, Alice now performs a projective\n measurement of her entire system onto the maximally entangled basis states. This is done\n by entangling $\\ket{\\psi}$ and $\\ket{q_1}$ via another 50-50 beamsplitter,\n before performing two homodyne measurements, in the $x$ and $p$ quadratures respectively.\n\n\n4. The results of these measurements are then transmitted to Bob, who performs both a\n position displacement (conditional on the $x$ measurement) and a momentum\n displacement (conditional on the $p$ measurement) to recover exactly the\n transmitted state $\\ket{\\psi}$.\n\n\nImporting Strawberry Fields\n---------------------------\n\nThe first thing we need to do is import Strawberry Fields; we do this with the following import\nstatements:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import strawberryfields as sf\nfrom strawberryfields.ops import *\n\nimport numpy as np\nfrom numpy import pi, sqrt\n\n# set the random seed\nnp.random.seed(42)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first import statement imports Strawberry Fields as ``sf``, allowing us to access the engine\nand backends; the second import statement imports all available CV gates into the global\nnamespace. Finally, we import $\\pi$ and the square root from ``NumPy`` so that we can pass angle\nparameters to gates such as beamsplitters, and perform some custom classical processing.\n\nProgram initialization\n----------------------\n\nWe can now initialize our quantum program by instantiating a\n:class:`~strawberryfields.Program` class:\n\n``sf.Program(num_subsystems, name=None)``\n\nwhere\n\n* ``num_subsystems`` (*int*) is the number of modes we want to initialize in our quantum register\n* ``name`` (*str*) is the name of the program (optional)\n\n

By default, Strawberry Fields uses the convention $\\hbar=2$ for the commutation relation\n $[\\x,\\p]=i\\hbar$.\n\n Other conventions can also be chosen by setting the global variable\n ``sf.hbar`` at the beginning of a session.\n\n The value of $\\hbar$ chosen modifies the application of the\n :class:`~strawberryfields.ops.Xgate` and :class:`~strawberryfields.ops.Zgate`, as well as the\n measurements returned by Homodyne measurement :class:`~strawberryfields.ops.MeasureHomodyne`, so this must be\n taken into account if the value of $\\hbar$ is modified. All other gates are\n unaffected.\n\n See `conventions` for more details.

\n\n![](/tutorials/images/teleport.svg)\n\n :width: 60%\n :align: center\n :target: javascript:void(0);\n\n.. raw:: html\n\n

\n\nto teleport the coherent state $\\ket{\\alpha}$ where $\\alpha=1+0.5i$:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "alpha = 1+0.5j\nr = np.abs(alpha)\nphi = np.angle(alpha)\n\nwith prog.context as q:\n # prepare initial states\n Coherent(r, phi) | q[0]\n Squeezed(-2) | q[1]\n Squeezed(2) | q[2]\n\n # apply gates\n BS = BSgate(pi/4, pi)\n BS | (q[1], q[2])\n BS | (q[0], q[1])\n\n # Perform homodyne measurements\n MeasureX | q[0]\n MeasureP | q[1]\n\n # Displacement gates conditioned on\n # the measurements\n Xgate(sqrt(2) * q[0].par) | q[2]\n Zgate(sqrt(2) * q[1].par) | q[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A couple of things to note here:\n\n* **The quantum register returned from the** ``prog.context`` **context manager is a sequence**.\n Individual modes can be accessed via standard Python indexing and slicing techniques.\n\n* **Preparing initial states, measurements, and gate operations all make use of the following\n syntax:**\n\n ``Operation([arg1, arg2, ...]) | reg``\n\n where the number of arguments depends on the specific operation, and ``reg`` is either a\n single mode or a sequence of modes, depending on how many modes the operation acts on. For a full\n list of operations and gates available, see the `quantum gates

By choosing a different phase for the 50-50 beamsplitter, that is, ``BSgate(pi/4,0)``, we can\n avoid having to negate the :class:`~strawberryfields.ops.Zgate` correction!

To avoid significant numerical error when working with the Fock backend, we need to make sure\n from now on that all initial states and gates we apply result in negligible amplitude in the\n Fock basis for Fock states $\\ket{n}, ~~n\\geq \\texttt{cutoff_dim}$. For example, to\n prepare a squeezed vacuum state in the $x$ quadrature with ``cutoff_dim=10``, a\n squeezing factor of $r=1$ provides an acceptable approximation, since\n $|\\braketD{n}{z}|^2<0.02$ for $n\\geq 10$.

A ``shots`` value different than 1 is currently only supported for one specific case: the\n :code:`MeasureFock/Measure` operation executed on the Gaussian backend.

The Fock state also provides the method\n :meth:`~strawberryfields.backends.BaseFockState.reduced_dm` for extracting the reduced density\n matrix automatically.