def test_gkp_wigner_compare_backends(self, fock_eps):
        """Test correct Wigner function are generated by comparing fock and bosonic outputs.
        Since the fock backend cannot simulate very small epsilon, we restrict to fock_eps>0.1."""
        theta = np.pi / 8
        phi = np.pi / 6
        ket = [theta, phi]
        xvec = np.linspace(-1, 1, 200)
        prog_fock = sf.Program(1)
        with prog_fock.context as q:
            sf.ops.GKP(epsilon=fock_eps, state=ket) | q
        cutoff = 100
        hbar = 2
        eng_fock = sf.Engine("fock",
                             backend_options={
                                 "cutoff_dim": cutoff,
                                 "hbar": hbar
                             })
        gkp_fock = eng_fock.run(prog_fock).state
        W_fock = gkp_fock.wigner(0, xvec, xvec)

        prog_bosonic = sf.Program(1)

        with prog_bosonic.context as q:
            sf.ops.GKP(epsilon=fock_eps, state=ket) | q
        hbar = 2
        eng_bosonic = sf.Engine("bosonic", backend_options={"hbar": hbar})
        gkp_bosonic = eng_bosonic.run(prog_bosonic).state
        W_bosonic = gkp_bosonic.wigner(0, xvec, xvec)
        assert np.allclose(W_fock, W_bosonic)
Example #2
0
def circuit(X):
    # Create a parameter with an initial value of 2.
    params = [make_param(name='phi', constant=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=params[0]) | (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, 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
    circuit_output = p1 / normalization

    return circuit_output
Example #3
0
 def setUp(self):
     """parameters"""
     self.hbar = 2.
     self.eng, _ = sf.Engine(3, hbar=self.hbar)
     self.r = 0.2
     self.th = 0.42
     self.phi = 0.123
Example #4
0
    def test_multimode_args_apply_operation(self):
        """Test applying an operation to multiple modes"""
        rval = 4.32
        thetaval = -0.654
        phival = 0.543

        @utils.operation(2)
        def dummy_func(r, theta, phi, q):
            Sgate(r) | q[0]
            BSgate(theta, phi) | (q[0], q[1])

        eng, q = sf.Engine(2)

        with eng:
            with pytest.raises(ValueError, match="Wrong number of subsystems"):
                dummy_func(rval, thetaval, phival) | q[0]

        with eng:
            dummy_func(rval, thetaval, phival) | q

        # check eng queue matches the operation
        assert len(eng.cmd_queue) == 2

        # check first queue op is Sgate(rval)
        assert isinstance(eng.cmd_queue[0].op, Sgate)
        assert eng.cmd_queue[0].reg == [q[0]]
        assert eng.cmd_queue[0].op.p[0].x == rval

        # check second queue op is BSgate(thetaval, phival)
        assert isinstance(eng.cmd_queue[1].op, BSgate)
        assert eng.cmd_queue[1].reg == list(q)
        assert eng.cmd_queue[1].op.p[0].x == thetaval
        assert eng.cmd_queue[1].op.p[1].x == phival
Example #5
0
    def test_call_function(self):
        """Test _call_function method for operation class"""
        rval = 4.32
        thetaval = -0.654
        phival = 0.543

        def dummy_func(r, theta, phi, q):
            Sgate(r) | q[0]
            BSgate(theta, phi) | (q[0], q[1])

        op = utils.operation(ns=1)
        op(dummy_func)(rval, thetaval, phival)

        eng, q = sf.Engine(2)

        with eng:
            res = op._call_function(q)

        # check register is returned
        assert res == q

        # check eng queue matches the operation
        assert len(eng.cmd_queue) == 2

        # check first queue op is Sgate(rval)
        assert isinstance(eng.cmd_queue[0].op, Sgate)
        assert eng.cmd_queue[0].reg == [q[0]]
        assert eng.cmd_queue[0].op.p[0].x == rval

        # check second queue op is BSgate(thetaval, phival)
        assert isinstance(eng.cmd_queue[1].op, BSgate)
        assert eng.cmd_queue[1].reg == list(q)
        assert eng.cmd_queue[1].op.p[0].x == thetaval
        assert eng.cmd_queue[1].op.p[1].x == phival
Example #6
0
    def run(self, fresh_inputs, desired_outputs=[]):
        print("Started a Run")
        # initialize engine and program objects
        eng = sf.Engine(backend="tf",
                        backend_options={"cutoff_dim": self.cutoff_dim})
        qnn = sf.Program(self.modes)

        # defining desired state
        target_state = np.zeros(self.cutoff_dim)
        target_state[-1] = 1
        self.target_state = tf.constant(target_state,
                                        dtype=tf.complex64)  # Desired output
        # self.target_state = desired_outputs

        self.modified_inputs = tf.placeholder(tf.float32,
                                              shape=[self.cutoff_dim])

        with qnn.context as q:
            print("Started and Working")
            for i in range(self.layers):
                self.layer(q)
                # self.record(i)

        # starting the engine
        results = eng.run(qnn, run_options={"eval": False})
        ket = results.state.ket()

        # defining cost function
        difference = tf.reduce_sum(tf.abs(ket - self.target_state))
        fidelity = tf.abs(tf.reduce_sum(tf.conj(ket) * self.target_state))**2
        cost = difference

        # setting up optimizer
        optimiser = tf.train.AdamOptimizer()
        minimize_cost = optimiser.minimize(cost)

        print("Beginning optimization")

        sess = tf.Session()
        sess.run(tf.global_variables_initializer())

        feed_dict = {self.modified_inputs: fresh_inputs}

        fidelity_before = sess.run(fidelity, feed_dict=feed_dict)

        for i in range(10):
            sess.run(minimize_cost, feed_dict=feed_dict)
            self.read_all()
            print(str(i) + " / 10")

        fidelity_after = sess.run(fidelity, feed_dict=feed_dict)

        print("Fidelity before optimization: " + str(fidelity_before))
        print("Fidelity after optimization: " + str(fidelity_after))
        print("\nTarget state: " +
              str(sess.run(self.target_state, feed_dict=feed_dict)))
        print("Output state: " +
              str(np.round(sess.run(ket, feed_dict=feed_dict), decimals=3)))

        qnn.draw_circuit()
Example #7
0
    def test_generate_code_with_engine(self, engine_kwargs):
        """Test generating code for a regular program with an engine"""
        prog = sf.Program(3)
        eng = sf.Engine(**engine_kwargs)

        with prog.context as q:
            ops.Sgate(0.54, 0) | q[0]
            ops.BSgate(0.45, np.pi / 2) | (q[0], q[2])
            ops.Sgate(3 * np.pi / 2, 0) | q[1]
            ops.BSgate(2 * np.pi, 0.62) | (q[0], q[1])
            ops.MeasureFock() | q[0]

        results = eng.run(prog)

        code = io.generate_code(prog, eng)

        code_list = code.split("\n")
        formatting_str = f"\"{engine_kwargs['backend']}\""
        if "backend_options" in engine_kwargs:
            formatting_str += (
                ", backend_options="
                f'{{"cutoff_dim": {engine_kwargs["backend_options"]["cutoff_dim"]}}}'
            )
        expected = prog_txt.format(engine_args=formatting_str).split("\n")

        for i, row in enumerate(code_list):
            assert row == expected[i]
Example #8
0
    def pre_measure(self):
        self.eng = sf.Engine("fock",
                             backend_options={"cutoff_dim": self.cutoff})
        results = self.eng.run(self.prog)

        self.state = results.state
        self.samples = results.samples
Example #9
0
    def test_all_samples_batched(self):
        """Test the case of storing all samples for batches"""
        batch_size = 2
        eng = sf.Engine("tf",
                        backend_options={
                            "batch_size": batch_size,
                            "cutoff_dim": 6
                        })
        prog = sf.Program(5)
        with prog.context as q:
            ops.MeasureFock() | q[2]
            ops.MeasureFock() | (q[1], q[3])
            ops.MeasureFock() | q[2]

        result = eng.run(prog)
        assert len(result.all_samples[1]) == 1
        assert len(result.all_samples[3]) == 1
        assert len(result.all_samples[2]) == 2

        assert np.array_equal(result.all_samples[1][0].numpy(),
                              np.array([[0], [0]]))
        assert np.array_equal(result.all_samples[3][0].numpy(),
                              np.array([[0], [0]]))
        assert np.array_equal(result.all_samples[2][0].numpy(),
                              np.array([[0], [0]]))
        assert np.array_equal(result.all_samples[2][1].numpy(),
                              np.array([[0], [0]]))
    def test_1x2_tf(self, hbar, tol):
        """Test a 1x2 lattice Bose-Hubbard model using TF"""
        try:
            import tensorflow as tf
        except (ImportError, ModuleNotFoundError):
            pytest.skip("TensorFlow not installed.")

        if tf.__version__[:3] != "1.3":
            pytest.skip("Incorrect TensorFlow version")

        sf.hbar = hbar
        prog = sf.Program(2)
        H = bose_hubbard(1, 2, self.J, self.U)

        with prog.context as q:
            Fock(2) | q[0]
            BoseHubbardPropagation(H, self.t, self.k) | q

        eng = sf.Engine("tf", backend_options={"cutoff_dim": 7})
        state = eng.run(prog).state

        Hm = -self.J*np.sqrt(2)*np.array([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) \
            + self.U*np.diag([1, 0, 1])
        init_state = np.array([1, 0, 0])
        exp = np.abs(np.dot(expm(-1j * self.t * Hm), init_state))**2

        assert np.allclose(state.fock_prob([2, 0]), exp[0], rtol=tol)
        assert np.allclose(state.fock_prob([1, 1]), exp[1], rtol=tol)
        assert np.allclose(state.fock_prob([0, 2]), exp[2], rtol=tol)
Example #11
0
def test_truncations(states, truncations=[10, 15, 20]):
    batch_size = states.shape[0]

    x = tf.placeholder(tf.complex64, shape=[batch_size, 3])

    eng, q = sf.Engine(1)
    with eng:
        Sgate(x[:, 0]) | q[0]
        Dgate(x[:, 1]) | q[0]
        Vgate(x[:, 2]) | q[0]

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())

    traces = np.zeros([batch_size, len(truncations)])
    for n in range(len(truncations)):
        state = eng.run('tf',
                        eval=False,
                        batch_size=batch_size,
                        cutoff_dim=truncations[n])
        trace = tf.real(state.trace())

        traces[:, n] = sess.run(trace, feed_dict={x: states})
        print("Evaluated T={}".format(truncations[n]))

    import matplotlib.pyplot as plt
    for n in range(len(truncations)):
        plt.subplot(len(truncations), 1, n + 1)
        plt.hist(traces[:, n], bins=25)
        plt.xlabel("Trace")
        plt.ylabel("Frequency")
        plt.ylim([0, batch_size])
    plt.show()
    def test_rotation(self, hbar):
        """Test rotation gives correct means and cov"""
        prog = sf.Program(1)
        eng = sf.Engine("gaussian")

        x = 0.2
        p = 0.3
        phi = 0.123
        H, t = rotation(phi, hbar=hbar)

        with prog.context as q:
            Xgate(x) | q[0]
            Zgate(p) | q[0]
            Sgate(2) | q[0]
            GaussianPropagation(H, t) | q[0]

        state = eng.run(prog).state

        # test the covariance matrix
        res = state.cov()
        V = np.diag([np.exp(-4), np.exp(4)]) * hbar / 2
        expected = rot(phi) @ V @ rot(phi).T
        assert np.allclose(res, expected)

        # test the vector of means
        res = state.means()
        exp = rot(phi) @ np.diag(np.exp([-2, 2])) @ np.array([x, p])
        assert np.allclose(res, exp)
    def test_squeezing(self, hbar):
        """Test squeezing gives correct means and cov"""
        prog = sf.Program(1)
        eng = sf.Engine("gaussian")

        x = 0.2
        p = 0.3
        r = 0.42
        phi = 0.123
        H, t = squeezing(r, phi, hbar=hbar)

        with prog.context as q:
            Xgate(x) | q[0]
            Zgate(p) | q[0]
            GaussianPropagation(H, t) | q[0]

        state = eng.run(prog).state

        # test the covariance matrix
        res = state.cov()
        S = rot(phi / 2) @ np.diag(np.exp([-r, r])) @ rot(phi / 2).T
        V = S @ S.T * hbar / 2
        assert np.allclose(res, V)

        # test the vector of means
        res = state.means()
        exp = S @ np.array([x, p])
        assert np.allclose(res, exp)
    def test_displaced_oscillator(self):
        """Test that a forced quantum oscillator produces the correct
        self.logTestName()
        trajectory in the phase space"""
        H = QuadOperator('q0 q0', 0.5)
        H += QuadOperator('p0 p0', 0.5)
        H -= QuadOperator('q0', self.F)

        res = []
        tlist = np.arange(0, self.t, self.dt)

        eng = sf.Engine("gaussian")

        for idx, t in enumerate(tlist):  #pylint: disable=unused-variable
            prog = sf.Program(1)

            with prog.context as q:
                Xgate(self.x0) | q[0]
                Zgate(self.p0) | q[0]
                GaussianPropagation(H, self.t) | q

            state = eng.run(prog).state
            eng.reset()
            res.append(state.means().tolist())

        res = np.array(res)[-1]
        expected = self.displaced_oscillator_soln(self.t)
        assert np.allclose(res, expected)
    def test_quadratic_phase(self, hbar):
        """Test quadratic phase gives correct means and cov"""
        prog = sf.Program(1)
        eng = sf.Engine("gaussian")

        x = 0.2
        p = 0.3
        s = 0.432
        H, t = quadratic_phase(s)

        with prog.context as q:
            Xgate(x) | q[0]
            Zgate(p) | q[0]
            GaussianPropagation(H, t) | q[0]

        state = eng.run(prog).state

        # test the covariance matrix
        res = state.cov()
        expected = np.array([[1, s], [s, 1 + s**2]]) * hbar / 2
        assert np.allclose(res, expected)

        # test the vector of means
        res = state.means()
        expected = np.array([x, p + s * x])
        assert np.allclose(res, expected)
Example #16
0
    def __init__(self):
        self.X = tf.placeholder(tf.float32, [1])
        self.Y = tf.placeholder(tf.float32, [1])
        self.alpha0 = tf.Variable(0.1)
        self.alpha1 = tf.Variable(0.1)
        self.alpha2 = tf.Variable(0.1)
        self.alpha3 = tf.Variable(0.1)
        self.alpha4 = tf.Variable(0.1)
        self.alpha5 = tf.Variable(0.1)
        self.alpha6 = tf.Variable(0.1)
        self.alpha7 = tf.Variable(0.1)
        self.alpha8 = tf.Variable(0.1)
        self.eng, self.q = sf.Engine(1)
        with self.eng:
            Dgate(self.X[0], 0.) | self.q[0]

            Dgate(self.alpha1) | self.q[0]
            Sgate(self.alpha2) | self.q[0]
            Vgate(self.alpha0) | self.q[0]

            Dgate(self.alpha4) | self.q[0]
            Sgate(self.alpha5) | self.q[0]
            Vgate(self.alpha3) | self.q[0]

            Dgate(self.alpha7) | self.q[0]
            Sgate(self.alpha8) | self.q[0]
            Vgate(self.alpha6) | self.q[0]
        self.state = self.eng.run('tf', cutoff_dim=10, eval=False)
        self.p0 = self.state.fock_prob([2])
        self.circuit_output = [self.p0 * 10]
        self.costf = tf.reduce_sum(tf.square(self.circuit_output[0] - self.Y))
        self.optimize = tf.train.GradientDescentOptimizer(0.1)
        self.trainop = self.optimize.minimize(self.costf)
        self.sess = tf.Session()
        self.sess.run(tf.global_variables_initializer())
Example #17
0
def circuit(X, params):

    eng, q = sf.Engine(2)

    # Since X is a batch of data, define a circuit for a single input
    # If you use the tf backend, you can pass batches into gates
    # like in the supervised tf learner example.
    def single_input_circuit(x):

        eng.reset()
        with eng:
            Dgate(x[0], 0.) | q[0]
            Dgate(x[1], 0.) | q[1]
            BSgate(phi=params[0]) | (q[0], q[1])
            BSgate() | (q[0], q[1])
        state = eng.run('fock', cutoff_dim=10, eval=True)

        # 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
        output = p1 / normalization
        return output

    # Apply the single circuit to every input in the batch
    circuit_output = [single_input_circuit(x) for x in X]

    return circuit_output
Example #18
0
def circuit():

    phi = make_param(name='phi', stdev=0.2, regularize=False)
    theta = make_param(name='theta', stdev=0.2, regularize=False)
    a = make_param(name='a', stdev=0.2, regularize=True, monitor=True)
    rtheta = make_param(name='rtheta',
                        stdev=0.2,
                        regularize=False,
                        monitor=True)
    r = make_param(name='r', stdev=0.2, regularize=True, monitor=True)
    kappa = make_param(name='kappa', stdev=0.2, regularize=True, monitor=True)

    eng, q = sf.Engine(2)

    with eng:
        BSgate(phi, theta) | (q[0], q[1])
        Dgate(a) | q[0]
        Rgate(rtheta) | q[0]
        Sgate(r) | q[0]
        Kgate(kappa) | q[0]

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

    return circuit_output
def test_cov_is_pure():
    """Tests space unrolling when going into the Gaussian backend"""
    delays = [1, 6, 36]
    modes = 216
    angles = np.concatenate([
        generate_valid_bs_sequence(delays, modes),
        generate_valid_r_sequence(delays, modes)
    ])
    net = modes + sum(delays)
    d = len(delays)
    n, N = get_mode_indices(delays)
    prog = sf.TDMProgram([N])
    vac_modes = sum(delays)

    with prog.context(*angles) as (p, q):
        Sgate(0.8) | q[n[0]]
        for i in range(d):
            Rgate(p[i + d]) | q[n[i]]
            BSgate(p[i], np.pi / 2) | (q[n[i + 1]], q[n[i]])

    prog.space_unroll()

    eng = sf.Engine(backend="gaussian")
    results = eng.run(prog)
    cov = results.state.cov()
    mu = np.zeros(len(cov))
    mu_vac, cov_vac = reduced_state(mu, cov, list(range(vac_modes)))
    mu_comp, cov_comp = reduced_state(mu, cov, list(range(vac_modes, net)))
    assert np.allclose(cov_vac, 0.5 * (sf.hbar) * np.identity(2 * vac_modes))
    assert is_pure_cov(cov_comp, hbar=sf.hbar)
    def setup_two_mode_circuit(self, setup_eng, cutoff):
        """Create the circuit for following tests"""
        eng_ref, q = setup_eng(2)

        S = ops.Sgate(2)
        B = ops.BSgate(2.234, -1.165)

        initial_state = np.complex64(
            np.random.rand(*[cutoff] * 4) + 1j * np.random.rand(*[cutoff] * 4))

        with eng_ref:
            ops.DensityMatrix(initial_state) | q
            S | q[0]
            B | q
            S | q[1]
            B | q

        eng, q = sf.Engine(2)

        with eng:
            S | q[0]
            B | q
            S | q[1]
            B | q

        rho = eng_ref.run().dm()
        return eng, rho, initial_state
    def test_cat_state_wigners(self, alpha, phi, representation):
        r"""Checks that the real and complex cat state representations
        have the same Wigner functions as the cat state from the Fock
        backend."""
        x = np.linspace(-2 * alpha, 2 * alpha, 100)
        p = np.linspace(-2 * alpha, 2 * alpha, 100)

        prog_complex_cat = sf.Program(1)
        with prog_complex_cat.context as qb:
            sf.ops.Catstate(alpha, phi, representation=representation) | qb[0]

        backend_bosonic = bosonic.BosonicBackend()
        backend_bosonic.run_prog(prog_complex_cat)
        wigner_bosonic = backend_bosonic.state().wigner(0, x, p)

        prog_cat_fock = sf.Program(1)
        with prog_cat_fock.context as qf:
            if alpha != 0:
                sf.ops.Catstate(alpha, phi) | qf[0]
            else:
                sf.ops.Vacuum() | qf[0]
        eng = sf.Engine("fock", backend_options={"cutoff_dim": 20})
        results = eng.run(prog_cat_fock)
        wigner_fock = results.state.wigner(0, x, p)

        assert np.allclose(wigner_bosonic, wigner_fock, rtol=1e-3, atol=1e-6)
Example #22
0
    def give_outcome_sf(self, beta, layer):
        """ Returns outcome according to current layer (needed to compute the "current" intensity).
            To accomplish this, it is used the Strawberryfields simulator, as a proof of principle that this
            can be easily done with this photonic platform.

            Notice that - if desired - the full experiment could be implemented with strawberryfields, considering a number of self.layers modes, and applying the displacements with the corresponding feed-forward. For the moment, as only the outcomes at each photodetector are needed to learn the correct displacements, we obtained them separately.

        """ #Actually, if all intensities are equal, you don't need to keep track of the layer here...
        effective_attenuation = np.prod(np.sin(self.at[:layer])) * np.cos(
            self.at[layer])  #Warning one!

        eng = sf.Engine("fock", backend_options={"cutoff_dim": 4})
        prog = sf.Program(1)

        with prog.context as q:
            Coherent(a=(effective_attenuation * self.phase * self.amplitude) -
                     beta) | q[0]
            MeasureFock() | q[0]
        results = eng.run(prog)

        outcome = np.array(outcome_from_fock(results).samples)[0]
        if outcome == 0:
            return 0
        else:
            return 1
Example #23
0
def circuit(params, a, m, 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 values
            in the following order:

            * ``'sq0' = (r, phi)``: the squeezing magnitude and phase on mode 0
            * ``'disp0' = (r, phi)``: the displacement magnitude and phase on mode 0
            * ``'sq1' = (r, phi)``: the squeezing magnitude and phase on mode 1
            * ``'disp1' = (r, phi)``: the displacement magnitude and phase on mode 1
            * ``'BS' = (theta, phi)``: the beamsplitter angles

        a (float): the ON state parameter
        m (int): the Fock state measurement 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
    sq0_r, sq0_phi, disp0_r, disp0_phi, sq1_r, sq1_phi, disp1_r, disp1_phi, theta, phi = params

    # quantum circuit prior to entering the beamsplitter
    prog1 = sf.Program(2)
    with prog1.context as q1:
        Sgate(sq0_r, sq0_phi) | q1[0]
        Dgate(disp0_r, disp0_phi) | q1[0]
        Sgate(sq1_r, sq1_phi) | q1[1]
        Dgate(disp1_r, disp1_phi) | q1[1]

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

    # norm of output state and probability
    prog_BS = sf.Program(2)
    with prog_BS.context as q1:
        BSgate(theta, phi) | (q1[0], q1[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[m, m]))

    # output state
    rhoB = rho[m, m] / prob

    fidelity = np.abs(np.trace(np.einsum('ij,jk->ik', rhoB, ONdm)))
    return (fidelity, prob, normIn, normOut, rhoB)
def ClosestClassicalState(r, K, eta, U, t):
    M = len(U)
    ap = eta * np.exp(2 * r) + 1 - eta
    an = eta * np.exp(-2 * r) + 1 - eta
    ss = 0.25 * np.log(ap / an)
    ns = 0.5 * (np.sqrt(ap * an) - 1)
    sc = 0.5 * np.log(2 * ns + 1)
    nt = 0.5 - 0.5 * np.sqrt(1 + 2 * t * np.sinh(2 * sc) * np.exp(2 * ss))
    s0 = 0.5 * np.log((2 * nt + 1) / t)
    if ss < s0:
        st = ss
        nt = ns
    else:
        s0 = 0.5 * np.log((2 * nt + 1) / t)
        st = s0

    # build the state
    prog = sf.Program(M)
    with prog.context as q:
        for i in range(K):
            Thermal(nt) | q[i]
            Sgate(st) | q[i]

        Interferometer(U) | q

    eng = sf.Engine('gaussian')
    result = eng.run(prog)
    cov = result.state.cov()
    return cov
Example #25
0
    def test_Ggate_optimization(self, setup_backend, pure):
        if not pure:
            pytest.skip("Test only runs on pure states")
        num_mode = 2
        eng = sf.Engine("tf", backend_options={"cutoff_dim": 5})
        prog = sf.Program(num_mode)
        optimizer = tf.keras.optimizers.SGD(learning_rate=0.001)
        S = tf.Variable(random_symplectic(num_mode), dtype=tf.complex128)
        d = tf.Variable(np.random.random(2 * num_mode), dtype=tf.complex128)

        prog = sf.Program(num_mode)
        with prog.context as q:
            ops.Ggate(S, d) | q

        loss_vals = []
        for _ in range(11):
            with tf.GradientTape() as tape:
                state_out = eng.run(prog).state.ket()
                loss_val = tf.abs(state_out[1, 1] - 0.25)**2
            eng.reset()
            grad_S, gradients_d = tape.gradient(loss_val, [S, d])
            optimizer.apply_gradients([(gradients_d, d)])
            sf.backends.tfbackend.ops.update_symplectic(S, grad_S, lr=0.05)
            loss_vals.append(loss_val)
            print(loss_val)
        assert all([bool(l1 > l2) for l1, l2 in zip(loss_vals, loss_vals[1:])])
    def build_circuit(self):
        params_counter = 0
        sgates = []
        dgates = []
        kgates = []
        vgates = []
        for gate_structure in self.gates_structure:
            if gate_structure[0] is Sgate:
                sgates.append(
                    ParametrizedGate(gate_structure[0], gate_structure[1], [
                        make_param(**gate_structure[2]),
                        make_param(**gate_structure[3])
                    ]))
            if gate_structure[0] is Dgate:
                dgates.append(
                    ParametrizedGate(gate_structure[0], gate_structure[1], [
                        make_param(**gate_structure[2]),
                        make_param(**gate_structure[3])
                    ]))
            if gate_structure[0] is Kgate:
                kgates.append(
                    ParametrizedGate(gate_structure[0], gate_structure[1],
                                     [make_param(**gate_structure[2])]))
            if gate_structure[0] is Vgate:
                vgates.append(
                    ParametrizedGate(gate_structure[0], gate_structure[1],
                                     [make_param(**gate_structure[2])]))

        eng, q = sf.Engine(self.n_qumodes)

        rl, U = takagi(self.adj_matrix)
        initial_squeezings = np.arctanh(rl)

        with eng:
            Interferometer(U) | q

            for i, squeeze_value in enumerate(initial_squeezings):
                Sgate(squeeze_value) | i

            if len(sgates) != 0:
                Interferometer(self.interferometer_matrix) | q
                for gate in sgates:
                    gate.gate(gate.params[0], gate.params[1]) | gate.qumodes

            if len(dgates) != 0:
                Interferometer(self.interferometer_matrix) | q
                for gate in dgates:
                    gate.gate(gate.params[0], gate.params[1]) | gate.qumodes

            for gate in kgates:
                gate.gate(gate.params[0]) | gate.qumodes

            for gate in vgates:
                gate.gate(gate.params[0]) | gate.qumodes

        circuit = {}
        circuit['eng'] = eng
        circuit['q'] = q

        return circuit
    def test_not_drawable(self, tmpdir):
        eng, q = sf.Engine(3)

        with eng:
            ops.BSgate(0, 2) | (q[0], q[2])

        with pytest.raises(NotDrawableException):
            eng.draw_circuit(print_queued_ops=True, tex_dir=tmpdir)
    def test_apply_gate(self):
        """Test successful gate application"""
        eng, _ = sf.Engine(2)

        with eng:
            ops.Dgate(0.5) | 0

        assert len(eng.cmd_queue) == 1
    def test_invalid(self):
        """cannot referring to a register with a non-integral or RegRef object"""
        eng, _ = sf.Engine(2)

        with eng:
            with pytest.raises(engine.RegRefError,
                               match="using integers and RegRefs"):
                ops.Dgate(0) | 1.2
    def test_wrong_engine(self):
        """Test that acting on a mode not belonging to the engine raises error"""
        eng, _ = sf.Engine(2)
        q_new = engine.RegRef(3)

        with eng:
            with pytest.raises(engine.RegRefError, match="Unknown RegRef."):
                ops.Dgate(0.5) | q_new