r"""
.. role:: html(raw)
    :format: html

.. _gate_teleport:

Gate teleportation
==================

    "Entanglement-assisted communication becomes entanglement-assisted computation"
    --- Furusawa [[1]_]

In the quantum state teleportation algorithm, the quantum state is transferred from the sender
to the receiver exactly. However, quantum teleportation can be used in a much more powerful
manner, by simultaneously processing and manipulating the teleported state; this is known as
**gate teleportation**.

But the biggest departure from its namesake is the method in which the gate to be 'teleported'
is applied; rather than applying a quantum unitary directly to the first qumode in the system,
the unitary is applied via the projective measurement of the first qumode onto a particular basis.
This measurement-based approach provides significant advantages over applying unitary gates
directly, for example by reducing resources, and in the application of experimentally
hard-to-implement gates [[1]_]. In fact, gate teleportation forms a universal
quantum computing primitive, and is a precursor to cluster state models of quantum computation
[[2]_][[3]_].


Implementation
--------------

First described by Gottesman and Chuang [[2]_] in the case of qubits, gate
teleportation was generalized for the CV case by Bartlett and Munro in 2003 [[4]_].
In an analogous process to the discrete-variable case, you begin with the algorithm for
**local state teleportation**:

.. image:: /tutorials/images/gate_teleport1.svg
    :align: center
    :width: 50%
    :target: javascript:void(0);

:html:`<br>`

Note that:

* Unlike the spatially-separated quantum state teleportation we considered in the previous section,
  **local teleportation** can transport the state using only two qumodes; the state we are
  teleporting is entangled directly with the squeezed vacuum state in the momentum space through
  the use of a controlled-phase gate.


* The state is then teleported to qumode :math:`q_1` via a homodyne measurement in the computational
  basis (the position quadrature).


* Like in the previous section, to recover the teleported state exactly, we must perform Weyl-Heisenberg
  corrections to :math:`q_1`; here, that would be :math:`F^\dagger X(m)^\dagger`. However, for convenience and
  simplicity, we write the circuit without the corrections applied explicitly.

Rather than simply teleporting the state as-is, we can introduce an arbitrary unitary :math:`U` that
acts upon :math:`\ket{\psi}`, as follows:

.. image:: /tutorials/images/gate_teleport2.svg
    :align: center
    :width: 50%
    :target: javascript:void(0);

:html:`<br>`

Now, the action of the unitary :math:`U` is similarly teleported along with the initial state
--- this is a trivial extension of the local teleportation circuit. In order to view this in
as a measurement-based universal quantum computing primitive, we make a couple of important changes:

* The inverse Fourier gate is absorbed into the measurement, making it a homodyne detector in
  the momentum quadrature

* The unitary gate :math:`U`, if diagonal in the computational basis (i.e., it is of the form
  :math:`U=e^{i f(\hat{x}^i)}`), commutes with the controlled-phase gate
  (:math:`CZ(s)=e^{i s ~\hat{x_1}\otimes\hat{x_2}/\hbar}`), and can be moved to the right of it.
  It is then also absorbed into the projective measurement.

.. image:: /tutorials/images/gate_teleport3.svg
    :align: center
    :width: 50%
    :target: javascript:void(0);

:html:`<br>`

Additional gates can now be added simply by introducing additional qumodes with the appropriate
projective measurements, all 'stacked vertically' (i.e., coupled to the each consecutive qumode
via a controlled-phase gate). From this primitive, the model of cluster state quantum computation
can be derived [[3]_].

.. note::

    What happens if the unitary is *not* diagonal in the computational basis? In this case,
    **feedforward** is required; additional qumodes and projective measurements are introduced,
    with successive measurements dependent on the previous result [[5]_].


Code
----

Consider the following gate teleportation circuit,

.. image:: /tutorials/images/gate_teleport_ex.svg
    :align: center
    :width: 70%
    :target: javascript:void(0);

:html:`<br>`

Here, the state :math:`\ket{\psi}`, a squeezed state with :math:`r=0.1`, is teleported to the
final qumode, with the quadratic phase gate (:class:`~strawberryfields.ops.Pgate`)
:math:`P(s)=e^{is\hat{x}^2/2\hbar}` teleported to act on it - with the quadratic phase gate
chosen as it is diagonal in the :math:`\x` quadrature. This can be easily implemented
using Strawberry Fields:
"""
import numpy as np

# set the random seed
np.random.seed(42)

import strawberryfields as sf
from strawberryfields.ops import *

gate_teleportation = sf.Program(3)

with gate_teleportation.context as q:
    # create initial states
    Squeezed(0.1) | q[0]
    Squeezed(-2)  | q[1]
    Squeezed(-2)  | q[2]

    # apply the gate to be teleported
    Pgate(0.5) | q[1]

    # conditional phase entanglement
    CZgate(1) | (q[0], q[1])
    CZgate(1) | (q[1], q[2])

    # projective measurement onto
    # the position quadrature
    Fourier.H | q[0]
    MeasureX  | q[0]
    Fourier.H | q[1]
    MeasureX  | q[1]

######################################################################
# Some important notes:
#
# * As with the :doc:`state teleportation circuit <run_teleportation>`, perfectly squeezed vacuum states
#   are not physically realizable; preparing the states with a squeezing factor of :math:`|r|=2`
#   (:math:`\sim 18\text{dB}`) is a reasonable approximation.
#
# ..
#
# * The Blackbird notation ``Operator.H`` denotes the Hermitian conjugate of the corresponding
#   operator.
#
# ..
#
# * Here, we do not make the corrections to the final state; this is left as an exercise to the reader.
#   For additional details, see the gate teleportation commutation relations derived by van Loock
#   [[5]_].
#
# Since all operations in the above gate teleportation circuit are Gaussian, we can use the
# ``"gaussian"`` backend:

eng = sf.Engine(backend="gaussian")

######################################################################
# Running the engine, and printing out the reduced state of modes 2
# and 3:

results = eng.run(gate_teleportation)
_, cov = results.state.reduced_gaussian([2])
print("Covariance matrix:\n", cov)

######################################################################
# We can also extract the measurement results of modes 0 and 1:
m0, m1 = results.samples[0]
print(m0, m1)

######################################################################
# To easily check that the output of the circuit is as expected, we can make sure that it agrees
# with the (uncorrected) state
#
# .. math:: X({q_1})FP(0.5)X(q_0)F \ket{z}.


check = sf.Program(1)

with check.context as q:
    # compare against the expected output
    # X(q1/sqrt(2)).F.P(0.5).X(q0/sqrt(0.5)).F.|z>
    # not including the corrections
    Squeezed(0.1) | q[0]
    Fourier       | q[0]
    Xgate(m0)     | q[0]
    Pgate(0.5)    | q[0]
    Fourier       | q[0]
    Xgate(m1)     | q[0]

eng = sf.Engine(backend="gaussian")
results = eng.run(check)
expected_cov = results.state.cov()

print("Expected covariance matrix:\n", expected_cov)

######################################################################
# These two states should be identical:

print(np.allclose(cov, expected_cov, atol=0.05, rtol=0))



######################################################################
# References
# ----------
#
# .. [1] A. Furusawa and P. van Loock. Quantum Teleportation and Entanglement:
#        A Hybrid Approach to Optical Quantum Information Processing. Wiley, 2011.
#        ISBN 9783527635290. URL: https://books.google.ca/books?id=eKxHZ0UHEU4C.
#
# .. [2] D. Gottesman and I. L. Chuang. Demonstrating the viability of universal quantum
#        computation using teleportation and single-qubit operations. Nature,
#        402:390–393, Nov 1999. arXiv:quant-ph/9908010, doi:10.1038/46503.
#
# .. [3] Mile Gu, Christian Weedbrook, Nicolas C. Menicucci, Timothy C. Ralph, and
#        Peter van Loock. Quantum computing with continuous-variable clusters.
#        Physical Review A, 79:062318, Jun 2009. doi:10.1103/PhysRevA.79.062318.
#
# .. [4] Stephen D. Bartlett and William J. Munro. Quantum teleportation of
#        optical quantum gates. Physical Review Letters, 90:117901, Mar 2003.
#        doi:10.1103/PhysRevLett.90.117901.
#
# .. [5] Peter van Loock. Examples of gaussian cluster computation. Journal of the
#        Optical Society of America B, 24(2):340–346, Feb 2007. doi:10.1364/JOSAB.24.000340.
