` .. image:: /tutorials/images/teleport.svg :width: 60% :align: center :target: javascript:void(0); :html:`

` This process can be explained as follows: 1. Here, qumodes :math:`q_1` and :math:`q_2` are initially prepared as (the unphysical) infinitely squeezed vacuum states in momentum and position space respectively, .. math:: &\ket{0}_x \sim \lim_{z\rightarrow\infty} S(z)\ket{0}\\ &\ket{0}_p \sim \lim_{z\rightarrow-\infty} S(z)\ket{0}=\frac{1}{\sqrt{\pi}}\int_{-\infty}^\infty \ket{x}~dx before being maximally entangled by a 50-50 beamsplitter: .. math:: BS(\pi/4,0)(\ket{0}_p\otimes\ket{0}_x) 2. These two qumodes are now spatially separated, with :math:`\ket{q_1}` held by Alice, and :math:`\ket{q_2}` held by Bob, with the two connected via the classical communication channels :math:`c_0` and :math:`c_1`. 3. To teleport her unknown state :math:`\ket{\psi}` to Bob, Alice now performs a projective measurement of her entire system onto the maximally entangled basis states. This is done by entangling :math:`\ket{\psi}` and :math:`\ket{q_1}` via another 50-50 beamsplitter, before performing two homodyne measurements, in the :math:`x` and :math:`p` quadratures respectively. 4. The results of these measurements are then transmitted to Bob, who performs both a position displacement (conditional on the :math:`x` measurement) and a momentum displacement (conditional on the :math:`p` measurement) to recover exactly the transmitted state :math:`\ket{\psi}`. Importing Strawberry Fields --------------------------- The first thing we need to do is import Strawberry Fields; we do this with the following import statements: """ import strawberryfields as sf from strawberryfields.ops import * import numpy as np from numpy import pi, sqrt # set the random seed np.random.seed(42) ###################################################################### # The first import statement imports Strawberry Fields as ``sf``, allowing us to access the engine # and backends; the second import statement imports all available CV gates into the global # namespace. Finally, we import :math:`\pi` and the square root from ``NumPy`` so that we can pass angle # parameters to gates such as beamsplitters, and perform some custom classical processing. # # Program initialization # ---------------------- # # We can now initialize our quantum program by instantiating a # :class:`~strawberryfields.Program` class: # # ``sf.Program(num_subsystems, name=None)`` # # where # # * ``num_subsystems`` (*int*) is the number of modes we want to initialize in our quantum register # * ``name`` (*str*) is the name of the program (optional) # # .. note:: # # By default, Strawberry Fields uses the convention :math:`\hbar=2` for the commutation relation # :math:`[\x,\p]=i\hbar`. # # Other conventions can also be chosen by setting the global variable # ``sf.hbar`` at the beginning of a session. # # The value of :math:`\hbar` chosen modifies the application of the # :class:`~strawberryfields.ops.Xgate` and :class:`~strawberryfields.ops.Zgate`, as well as the # measurements returned by Homodyne measurement :class:`~strawberryfields.ops.MeasureHomodyne`, so this must be # taken into account if the value of :math:`\hbar` is modified. All other gates are # unaffected. # # See :ref:`conventions` for more details. # # Therefore, to initialize a program on three quantum registers, we write: prog = sf.Program(3) ###################################################################### # Circuit construction # -------------------- # # To prepare states and apply gates to the quantum register ``q``, we must be inside the context of # the program we initialized using the ``with`` statement. Everything within the program context is # written using the :ref:`Blackbird quantum programming language

# # .. image:: /tutorials/images/teleport.svg # :width: 60% # :align: center # :target: javascript:void(0); # # .. raw:: html # #

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