def test_eng_run_state_reduced_dm(self, setup_eng, cutoff, tol):
        """Tests whether the reduced_density matrix of the returned state
        is a Tensor object when executed with `eng.run`."""
        eng, prog = setup_eng(1)

        with prog.context as q:
            Dgate(ALPHA) | q

        state = eng.run(prog).state
        rho = state.reduced_dm([0])
        assert isinstance(rho, tf.Tensor)

        ket = coherent_state(ALPHA, cutoff)
        coh_dm = np.einsum("i,j->ij", ket, ket.conj())
        assert np.allclose(rho, coh_dm, atol=tol, rtol=0.0)
    def test_eval_true_state_all_fock_probs(self, setup_eng, cutoff,
                                            batch_size, tol):
        """Tests whether the Fock-basis probabilities of the state return
        a Tensor with the correct value."""
        eng, prog = setup_eng(2)

        with prog.context as q:
            Dgate(ALPHA) | q[0]
            Dgate(-ALPHA) | q[1]

        state = eng.run(prog).state
        probs = state.all_fock_probs()

        assert isinstance(probs, tf.Tensor)

        probs = probs.numpy().flatten()
        ref_probs = (np.abs(
            np.outer(coherent_state(ALPHA, cutoff),
                     coherent_state(-ALPHA, cutoff))).flatten()**2)

        if batch_size is not None:
            ref_probs = np.tile(ref_probs, batch_size)

        assert np.allclose(probs, ref_probs, atol=tol, rtol=0.0)
Ejemplo n.º 3
0
def circuit():

    # Create a parameter with an initial value of 0.1
    params = [make_param(name='alpha', constant=0.1)]

    eng, q = sf.Engine(1)

    with eng:
        Dgate(params[0]) | q[0]

    state = eng.run('tf', cutoff_dim=7, eval=False)

    # As the output we take the probability of measuring one photon in the mode
    prob = state.fock_prob([1])
    circuit_output = tf.identity(prob, name="prob")
    return circuit_output
    def test_eng_run_state_ket(self, setup_eng, cutoff, pure, tol):
        """Tests whether the ket of the returned state is a
        Tensor object when executed with `eng.run`."""
        if not pure:
            pytest.skip("Tested only for pure states")

        eng, prog = setup_eng(1)
        with prog.context as q:
            Dgate(ALPHA) | q

        state = eng.run(prog).state
        ket = state.ket()
        assert isinstance(ket, tf.Tensor)

        coh_ket = coherent_state(ALPHA, cutoff)
        assert np.allclose(ket, coh_ket, atol=tol, rtol=0.0)
    def test_eng_run_state_mean_photon(self, setup_eng, tol):
        """Tests whether the local mean photon number of the state is
        Tensor object when executed with `eng.run`."""
        eng, prog = setup_eng(1)

        with prog.context as q:
            Dgate(ALPHA) | q

        state = eng.run(prog).state
        nbar, var = state.mean_photon(0)
        assert isinstance(nbar, tf.Tensor)
        assert isinstance(var, tf.Tensor)

        ref_nbar = np.abs(ALPHA) ** 2
        ref_var = np.abs(ALPHA) ** 2
        assert np.allclose(nbar, ref_nbar, atol=tol, rtol=0.0)
        assert np.allclose(var, ref_var, atol=tol, rtol=0.0)
    def test_eng_run_state_quad_expectation(self, setup_eng, tol, hbar):
        """Tests whether the local quadrature expectation of the state is
        Tensor object when executed with `eng.run`."""
        eng, prog = setup_eng(1)

        with prog.context as q:
            Dgate(ALPHA) | q

        state = eng.run(prog).state
        e, v = state.quad_expectation(0, 0)
        assert isinstance(e, tf.Tensor)
        assert isinstance(v, tf.Tensor)

        true_exp = np.sqrt(hbar / 2.0) * (ALPHA + np.conj(ALPHA))
        true_var = hbar / 2.0
        assert np.allclose(e, true_exp, atol=tol, rtol=0.0)
        assert np.allclose(v, true_var, atol=tol, rtol=0.0)
    def test_eng_run_state_dm(self, pure, cutoff, setup_eng, tol):
        """Tests whether the density matrix of the returned state is an
        Tensor object when executed with `eng.run`."""
        if not pure:
            pytest.skip("Tested only for pure states")

        eng, prog = setup_eng(1)

        with prog.context as q:
            Dgate(ALPHA) | q

        state = eng.run(prog).state
        dm = state.dm()
        assert isinstance(dm, tf.Tensor)

        ket = coherent_state(ALPHA, cutoff)
        coh_dm = np.einsum("i,j->ij", ket, ket.conj())
        assert np.allclose(dm, coh_dm, atol=tol, rtol=0.0)
Ejemplo n.º 8
0
def circuit(params):

    eng, q = sf.Engine(1)

    with eng:
        Dgate(params[0]) | q[0]

    state = eng.run('fock', cutoff_dim=7)

    circuit_output = state.fock_prob([1])
    trace = state.trace()

    # Log the trace of the state to check if it is 1
    log = {'Prob': circuit_output, 'Trace': trace}

    # The second return value can be an optional log dictionary
    # of one or more values
    return circuit_output, log
Ejemplo n.º 9
0
def circuit():

    # This time we want to keep the parameter small via regularization and visualize its evolution in tensorboard
    params = [
        make_param(name='alpha', constant=0.1, regularize=True, monitor=True)
    ]
    eng, q = sf.Engine(1)

    with eng:
        Dgate(params[0]) | q[0]

    state = eng.run('tf', cutoff_dim=7, eval=False)

    circuit_output = state.fock_prob([1])

    # The identity() function allows us to give this tensor a name
    # which we can refer to below
    circuit_output = tf.identity(circuit_output, name="prob")
    trace = tf.identity(state.trace(), name='trace')

    return circuit_output
    def test_displaced_squeezed_mean_photon_gradient(self, setup_eng, cutoff, tol, batch_size):
        """Test whether the gradient of the mean photon number of a displaced squeezed
        state is correct.

        .. note::

            As this test contains multiple gates being applied to the program,
            this test will fail in TensorFlow 2.1 due to the bug discussed in
            https://github.com/tensorflow/tensorflow/issues/37307, if `tf.einsum` is being used
            in ``tfbackend/ops.py`` rather than _einsum_v1.
        """
        if batch_size is not None:
            pytest.skip(
                "Cannot calculate gradient in batch mode, as tape.gradient "
                "cannot differentiate non-scalar output."
            )

        eng, prog = setup_eng(1)

        with prog.context as q:
            Sgate(prog.params("r"), prog.params("phi")) | q
            Dgate(prog.params("a")) | q

        a = tf.Variable(ALPHA)
        r = tf.Variable(0.105)
        phi = tf.Variable(0.123)

        with tf.GradientTape() as tape:
            state = eng.run(prog, args={"a": a, "r": r, "phi": phi}).state
            mean, _ = state.mean_photon(0)

        # test the mean and variance of the photon number is correct
        mean_ex = a ** 2 + tf.sinh(r) ** 2
        assert np.allclose(mean, mean_ex, atol=tol, rtol=0)

        # test the gradient of the mean is correct
        grad = tape.gradient(mean, [a, r, phi])
        grad_ex = [2 * a, 2 * tf.sinh(r) * tf.cosh(r), 0]
        assert np.allclose(grad, grad_ex, atol=tol, rtol=0)
    def test_displaced_thermal_mean_photon_gradient(self, setup_eng, tol, batch_size):
        """Tests whether the gradient for the mean photon variance
        on a displaced thermal state is correct:

        E(n)=|a|^2+nbar and var(n)=var_th+|a|^2(1+2nbar)
        """
        if batch_size is not None:
            pytest.skip(
                "Cannot calculate gradient in batch mode, as tape.gradient "
                "cannot differentiate non-scalar output."
            )

        eng, prog = setup_eng(1)

        alpha = prog.params("alpha")
        nbar = prog.params("nbar")

        with prog.context as q:
            Thermal(nbar) | q
            Dgate(alpha) | q

        a = tf.Variable(0.2)
        n = tf.Variable(0.052)

        with tf.GradientTape() as tape:
            state = eng.run(prog, args={"nbar": n, "alpha": a}).state
            mean, var = state.mean_photon(0)

        # test the mean and variance of the photon number is correct
        mean_ex = a ** 2 + n
        var_ex = n ** 2 + n + a ** 2 * (1 + 2 * n)
        assert np.allclose(mean, mean_ex, atol=tol, rtol=0)
        assert np.allclose(var, var_ex, atol=tol, rtol=0)

        # test the gradient of the variance is correct
        grad = tape.gradient(var, [a, n])
        grad_ex = [2 * a * (1 + 2 * n), 2 * n + 1 + 2 * a ** 2]
        assert np.allclose(grad, grad_ex, atol=tol, rtol=0)
Ejemplo n.º 12
0
def qnn_layer(layer_number):
    with tf.name_scope('layer_{}'.format(layer_number)):
        BSgate(bs_variables[layer_number, 0, 0, 0], bs_variables[layer_number, 0, 0, 1]) \
        | (q[0], q[1])

        for i in range(mode_number):
            Rgate(phase_variables[layer_number, i, 0]) | q[i]

        for i in range(mode_number):
            Sgate(tf.clip_by_value(sq_magnitude_variables[layer_number, i], -sq_clip, sq_clip),
                  sq_phase_variables[layer_number, i]) | q[i]

        BSgate(bs_variables[layer_number, 0, 1, 0], bs_variables[layer_number, 0, 1, 1]) \
        | (q[0], q[1])

        for i in range(mode_number):
            Rgate(phase_variables[layer_number, i, 1]) | q[i]

        for i in range(mode_number):
            Dgate(tf.clip_by_value(disp_magnitude_variables[layer_number, i], -disp_clip,
                                   disp_clip), disp_phase_variables[layer_number, i]) | q[i]

        for i in range(mode_number):
            Kgate(tf.clip_by_value(kerr_variables[layer_number, i], -kerr_clip, kerr_clip)) | q[i]
def circuit(params, a, m1, m2, cutoff):
    """Runs the constrained variational circuit with specified parameters,
    returning the output fidelity to the requested ON state, as well as
    the post-selection probability.

    Args:
        params (list): list of gate parameters for the constrained
            variational quantum circuit. This should contain the following 15 values
            in the following order:

            * ``sq_r0, sq_r1, sq_r2``: the squeezing magnitudes applied to the first three modes
            * ``sq_phi0, sq_phi1, sq_phi2``: the squeezing phase applied to the first three modes
            * ``d_r0, d_r1, d_r2``: the displacement magnitudes applied to the first three modes
            * ``bs_theta1, bs_theta2, bs_theta3``: the 3-mode interferometer beamsplitter angles theta
            * ``bs_phi1, bs_phi2, bs_phi3``: the 3-mode interferometer beamsplitter phases phi

        a (float): the ON state parameter
        m1 (int): the Fock state measurement of mode 0 to be post-selected
        m2 (int): the Fock state measurement of mode 1 to be post-selected
        cutoff (int): the Fock basis truncation

    Returns:
        tuple: a tuple containing the output fidelity to the target ON state,
            the probability of post-selection, the state norm before entering the beamsplitter,
            the state norm after exiting the beamsplitter, and the density matrix of the output state.
    """
    # define target state
    ONdm = on_state(a, cutoff)

    # unpack circuit parameters
    # squeezing magnitudes
    sq_r = params[:3]
    # squeezing phase
    sq_phi = params[3:6]
    # displacement magnitudes (assume displacement is real for now)
    d_r = params[6:9]
    # beamsplitter theta
    bs_theta1, bs_theta2, bs_theta3 = params[9:12]
    # beamsplitter phi
    bs_phi1, bs_phi2, bs_phi3 = params[12:]

    # quantum circuit prior to entering the beamsplitter
    prog = sf.Program(3)

    with prog.context as q:
        for k in range(3):
            Sgate(sq_r[k], sq_phi[k]) | q[k]
            Dgate(d_r[k]) | q[k]

    eng = sf.Engine("fock", backend_options={"cutoff_dim": cutoff})
    stateIn = eng.run(prog).state
    normIn = np.abs(stateIn.trace())

    # norm of output state and probability
    prog_BS = sf.Program(3)
    with prog_BS.context as q:
        BSgate(bs_theta1, bs_phi1) | (q[0], q[1])
        BSgate(bs_theta2, bs_phi2) | (q[1], q[2])
        BSgate(bs_theta3, bs_phi3) | (q[0], q[1])

    stateOut = eng.run(prog_BS).state
    normOut = np.abs(stateOut.trace())
    rho = stateOut.dm()

    # probability of meausring m1 and m2
    prob = np.abs(np.trace(rho[m1, m1, m2, m2]))

    # output state
    rhoC = rho[m1, m1, m2, m2]/prob

    #fidelity with the target
    fidelity = np.abs(np.trace(np.einsum('ij,jk->ik', rhoC, ONdm)))
    return (fidelity, prob, normIn, normOut, rhoC)
        Sgate(tf.clip_by_value(sqr2[l], -sq_clip, sq_clip), sqphi2[l]) | q[1]
        BSgate(theta2[l], phi2[l]) | (q[0], q[1])
        Rgate(r2[l]) | q[0]
        Dgate(tf.clip_by_value(dr1[l], -disp_clip, disp_clip), dphi1[l]) | q[0]
        Dgate(tf.clip_by_value(dr2[l], -disp_clip, disp_clip), dphi2[l]) | q[1]
        Kgate(tf.clip_by_value(kappa1[l], -kerr_clip, kerr_clip)) | q[0]
        Kgate(tf.clip_by_value(kappa2[l], -kerr_clip, kerr_clip)) | q[1]


# StrawberryFields quantum simulator of 2 optical modes
engine, q = sf.Engine(num_subsystems=2)

# Definition of the CV quantum network
with engine:
    # State preparation
    Dgate(disps_alpha) | q[0]
    Dgate(disps_beta) | q[1]
    # Sequence of variational layers
    for i in range(depth):
        layer(i)

# Symbolic evaluation of the output state
state = engine.run('tf', cutoff_dim=cutoff, eval=False, batch_size=num_images)
ket = state.ket()
trace = tf.abs(state.trace())

# Projection on the subspace of up to im_dim-1 photons for each mode.
ket_reduced = ket[:, :im_dim, :im_dim]
norm = tf.sqrt(tf.abs(tf.reduce_sum(tf.conj(ket_reduced) * ket_reduced, axis=[1, 2])))
# Since norm has shape [num_images] while ket_reduced has shape [num_images,im_dim,im_dim]
# we need to add 2 extra dimensions to the norm tensor.
Ejemplo n.º 15
0
def circuit(X):
    num_qubits = X.get_shape().as_list()[1]

    phi_1 = make_param(name='phi_1',
                       stdev=np.sqrt(2) / num_qubits,
                       shape=[depth, num_qubits],
                       regularize=False)
    theta_1 = make_param(name='theta_1',
                         stdev=np.sqrt(2) / num_qubits,
                         shape=[depth, num_qubits],
                         regularize=False)
    a = make_param(name='a',
                   stdev=np.sqrt(2) / num_qubits,
                   shape=[depth, num_qubits],
                   regularize=False,
                   monitor=True)
    rtheta_1 = make_param(name='rtheta_1',
                          stdev=np.sqrt(2) / num_qubits,
                          shape=[depth, num_qubits],
                          regularize=False,
                          monitor=True)
    r = make_param(name='r',
                   stdev=np.sqrt(2) / num_qubits,
                   shape=[depth, num_qubits],
                   regularize=False,
                   monitor=True)
    kappa = make_param(name='kappa',
                       stdev=np.sqrt(2) / num_qubits,
                       shape=[depth, num_qubits],
                       regularize=False,
                       monitor=True)
    phi_2 = make_param(name='phi_2',
                       stdev=np.sqrt(2) / num_qubits,
                       shape=[depth, num_qubits],
                       regularize=False)
    theta_2 = make_param(name='theta_2',
                         stdev=np.sqrt(2) / num_qubits,
                         shape=[depth, num_qubits],
                         regularize=False)
    rtheta_2 = make_param(name='rtheta_2',
                          stdev=np.sqrt(2) / num_qubits,
                          shape=[depth, num_qubits],
                          regularize=False,
                          monitor=True)

    def layer(i, size):
        Rgate(rtheta_1[i, 0]) | (q[0])
        BSgate(phi_1[i, 0], 0) | (q[0], q[1])
        Rgate(rtheta_1[i, 2]) | (q[1])

        for j in range(size):
            Sgate(r[i, j]) | q[j]

        Rgate(rtheta_2[i, 0]) | (q[0])
        BSgate(phi_2[i, 0], 0) | (q[0], q[1])
        Rgate(rtheta_2[i, 2]) | (q[2])
        BSgate(phi_2[i, 2], theta_2[i, 3]) | (q[2], q[3])
        Rgate(rtheta_2[i, 1]) | (q[1])
        BSgate(phi_2[i, 1], 0) | (q[1], q[2])
        Rgate(rtheta_2[i, 0]) | (q[0])
        BSgate(phi_2[i, 0], 0) | (q[0], q[1])
        Rgate(rtheta_2[i, 0]) | (q[0])
        Rgate(rtheta_2[i, 1]) | (q[1])
        Rgate(rtheta_2[i, 2]) | (q[2])
        Rgate(rtheta_2[i, 3]) | (q[3])
        BSgate(phi_2[i, 2], 0) | (q[2], q[3])
        Rgate(rtheta_2[i, 2]) | (q[2])
        BSgate(phi_2[i, 1], 0) | (q[1], q[2])
        Rgate(rtheta_2[i, 1]) | (q[1])

        for j in range(size):
            Kgate(kappa[i, j]) | q[j]

    eng, q = sf.Engine(num_qubits)

    with eng:
        for i in range(num_qubits):
            Dgate(X[:, i], 0.) | q[i]
        for d in range(depth):
            layer(d, num_qubits)

    num_inputs = X.get_shape().as_list()[0]
    state = eng.run('tf', cutoff_dim=10, eval=False, batch_size=num_inputs)
    circuit_output, var0 = state.quad_expectation(0)

    return circuit_output
import strawberryfields as sf
from strawberryfields.ops import Dgate, BSgate
import tensorflow as tf
from qmlt.tf.helpers import make_param
from qmlt.tf import CircuitLearner

# Define the variational circuit and its output.
X = tf.placeholder(tf.float32, shape=[2])
y = tf.placeholder(tf.float32)
phi = tf.Variable(2.)

eng, q = sf.Engine(2)

with eng:
    # Note that we are feeding 1-d tensors into gates, not scalars!
    Dgate(X[0], 0.) | q[0]
    Dgate(X[1], 0.) | q[1]
    BSgate(phi) | (q[0], q[1])
    BSgate() | (q[0], q[1])

# We have to tell the engine how big the batches (first dim of X) are
# which we feed into gates
num_inputs = X.get_shape().as_list()[0]
state = eng.run('tf', cutoff_dim=10, eval=False)

# Define the output as the probability of measuring |0,2> as opposed to |2,0>
p0 = state.fock_prob([0, 2])
p1 = state.fock_prob([2, 0])
normalization = p0 + p1 + 1e-10
circuit_output = p1 / normalization
Ejemplo n.º 17
0
    # We have to tell the engine how big the batches (first dim of X) are
    # which we feed into gates
    num_inputs = X.get_shape().as_list()[0]
    state = eng.run('tf', cutoff_dim=10, eval=False, batch_size=num_inputs)

    # Define the output as the probability of measuring |0,2> as opposed to |2,0>
    p0 = state.fock_prob([0, 2])
    p1 = state.fock_prob([2, 0])
    normalization = p0 + p1 + 1e-10
    output1 = p1 / normalization
    
    
    with eng:
        # Note that we are feeding 1-d tensors into gates, not scalars!
        X1 = output1
        Dgate(X1, 0.) | q[0]
        Dgate(0., X1) | q[1]
        BSgate(phi=params[1]) | (q[0], q[1])
        BSgate() | (q[0], q[1])
        Vgate(params[5]) | q[0]
        Vgate(params[6]) | q[1]

    # We have to tell the engine how big the batches (first dim of X) are
    # which we feed into gates
    num_inputs1 = X1.get_shape().as_list()[0]
    state2 = eng.run('tf', cutoff_dim=10, eval=False, batch_size=num_inputs1)

    # Define the output as the probability of measuring |0,2> as opposed to |2,0>
    p00 = state2.fock_prob([0, 2])
    p01 = state2.fock_prob([2, 0])
    normalization1 = p00 + p01 + 1e-10