Example #1
0
    def prepare_gaussian_state(self, r, V, modes):
        if isinstance(modes, int):
            modes = [modes]

        # make sure number of modes matches shape of r and V
        N = len(modes)
        if len(r) != 2 * N:
            raise ValueError("Length of means vector must be twice the number of modes.")
        if V.shape != (2 * N, 2 * N):
            raise ValueError(
                "Shape of covariance matrix must be [2N, 2N], where N is the number of modes."
            )

        # Include these lines to accommodate out of order modes, e.g.[1,0]
        ordering = np.append(np.argsort(modes), np.argsort(modes) + len(modes))
        V = V[ordering, :][:, ordering]
        r = r[ordering]

        # convert xp-ordering to symmetric ordering
        means = np.vstack([r[:N], r[N:]]).reshape(-1, order="F")
        C = changebasis(N)
        cov = C @ V @ C.T

        self.circuit.from_covmat(cov, modes)
        self.circuit.from_mean(means, modes)
Example #2
0
    def prepare_gaussian_state(self, r, V, modes):
        r"""Prepare the given Gaussian state (via the provided vector of
        means and the covariance matrix) in the specified modes.

        The requested mode(s) is/are traced out and replaced with the given Gaussian state.

        Args:
            r (array): the vector of means in xp ordering.
            V (array): the covariance matrix in xp ordering.
            modes (int or Sequence[int]): which mode to prepare the state in
                If the modes are not sorted, this is take into account when preparing the state.
                i.e., when a two mode state is prepared in modes=[3,1], then the first
                mode of state goes into mode 3 and the second mode goes into mode 1 of the simulator.
        """
        if isinstance(modes, int):
            modes = [modes]

        # make sure number of modes matches shape of r and V
        N = len(modes)
        if len(r) != 2 * N:
            raise ValueError(
                "Length of means vector must be twice the number of modes.")
        if V.shape != (2 * N, 2 * N):
            raise ValueError(
                "Shape of covariance matrix must be [2N, 2N], where N is the number of modes."
            )

        # convert xp-ordering to symmetric ordering
        means = vstack([r[:N], r[N:]]).reshape(-1, order='F')
        C = changebasis(N)
        cov = C @ V @ C.T

        self.circuit.fromscovmat(cov, modes)
        self.circuit.fromsmean(means, modes)
Example #3
0
    def test_three_mode_arbitrary(self):
        """Test that the correct result is returned for an arbitrary quadratic polynomial"""
        self.logTestName()

        A = np.array([[ 0.7086495 , -0.39299695,  0.30536448,  0.48822049,  0.64987373, 0.7020327 ],
                      [-0.39299695,  0.0284145 ,  0.53202656,  0.20232385,  0.26288656, 0.20772833],
                      [ 0.30536448,  0.53202656,  0.28126466,  0.64192545, -0.36583748, 0.51704656],
                      [ 0.48822049,  0.20232385,  0.64192545,  0.51033017,  0.29129713, 0.77103581],
                      [ 0.64987373,  0.26288656, -0.36583748,  0.29129713,  0.37646972, 0.2383589 ],
                      [ 0.7020327 ,  0.20772833,  0.51704656,  0.77103581,  0.2383589 ,-0.96494418]])

        d = np.array([ 0.71785224,  -0.80064627,  0.08799823,  0.76189805,  0.99665321, -0.60777437])
        k = 0.123

        self.circuit.reset(pure=self.kwargs['pure'])

        a_list = [0.044+0.023j, 0.0432+0.123j, -0.12+0.04j]
        r_list = [0.1065, 0.032, -0.123]
        phi_list = [0.897, 0.31, 0.432]

        mu = np.zeros([6])
        cov = np.zeros([6, 6])

        # squeeze and displace each mode
        for i, (a_, r_, phi_) in enumerate(zip(a_list, r_list, phi_list)):
            self.circuit.prepare_displaced_squeezed_state(a_, r_, phi_, i)
            mu[2*i:2*i+2] = R(self.qphi).T @ np.array([a_.real, a_.imag]) * np.sqrt(2*self.hbar)
            cov[2*i:2*i+2, 2*i:2*i+2] = R(self.qphi).T @ squeezed_cov(r_, phi_, hbar=self.hbar) @ R(self.qphi)

        # apply a beamsplitter to the modes
        self.circuit.beamsplitter(1/np.sqrt(2), 1/np.sqrt(2), 0, 1)
        self.circuit.beamsplitter(1/np.sqrt(2), 1/np.sqrt(2), 1, 2)

        state = self.circuit.state()
        mean, var = state.poly_quad_expectation(A, d, k, phi=self.qphi)

        # apply a beamsplitter to vector of means and covariance matrices
        t = 1/np.sqrt(2)
        BS = np.array([[ t,  0,  -t,  0],
                       [ 0,  t,  0,  -t],
                       [ t,  0,  t,  0],
                       [ 0,  t,  0,  t]])

        S1 = block_diag(BS, np.identity(2))
        S2 = block_diag(np.identity(2), BS)

        C = changebasis(3)
        mu = C.T @ S2 @ S1 @ mu
        cov = C.T @ S2 @ S1 @ cov @ S1.T @ S2.T @ C

        modes = list(np.arange(6).reshape(2,-1).T)

        mean_ex = np.trace(A @ cov) + mu @ A @ mu + mu @ d + k
        var_ex = 2*np.trace(A @ cov @ A @ cov) + 4*mu.T @ A.T @ cov @ A @ mu + d.T @ cov @ d \
            + 2*mu.T @ A.T @ cov @ d + 2*d.T @ cov @ A @ mu \
            - np.sum([np.linalg.det(self.hbar*A[:, m][n]) for m in modes for n in modes])

        self.assertAlmostEqual(mean, mean_ex, delta=self.tol)
        self.assertAlmostEqual(var, var_ex, delta=self.tol)
    def test_means_changebasis(self):
        """Test the change of basis function applied to vectors. This function
        converts from xp to symmetric ordering, and vice versa."""
        C = so.changebasis(3)
        means_xp = [1, 2, 3, 4, 5, 6]
        means_symmetric = [1, 4, 2, 5, 3, 6]

        assert np.all(C @ means_xp == means_symmetric)
        assert np.all(C.T @ means_symmetric == means_xp)
    def test_cov_changebasis(self):
        """Test the change of basis function applied to matrices. This function
        converts from xp to symmetric ordering, and vice versa."""
        C = so.changebasis(2)
        cov_xp = np.array(
            [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
        )

        cov_symmetric = np.array(
            [[0, 2, 1, 3], [8, 10, 9, 11], [4, 6, 5, 7], [12, 14, 13, 15]]
        )

        assert np.all(C @ cov_xp @ C.T == cov_symmetric)
        assert np.all(C.T @ cov_symmetric @ C == cov_xp)
Example #6
0
    def test_rotated_squeezed(self, setup_eng, hbar, tol):
        """Testing a rotated squeezed state"""
        eng, prog = setup_eng(3)

        r = 0.1
        phi = 0.2312
        v1 = (hbar / 2) * np.diag([np.exp(-r), np.exp(r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with prog.context as q:
            ops.Gaussian(cov, decomp=False) | q

        state = eng.run(prog).state
        assert np.allclose(state.cov(), cov, atol=tol)
Example #7
0
    def test_covariance_rotated_squeezed(self):
        self.logTestName()
        q = self.eng.register

        r = 0.1
        phi = 0.2312
        v1 = (self.hbar / 2) * np.diag([np.exp(-r), np.exp(r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with self.eng:
            Gaussian(cov, decomp=False) | q

        state = self.eng.run()
        self.assertAllAlmostEqual(state.cov(), cov, delta=self.tol)
Example #8
0
    def test_rotated_squeezed(self, setup_eng, hbar, tol):
        """Testing decomposed rotated squeezed state"""
        eng, q = setup_eng(3)

        r = 0.1
        phi = 0.2312
        v1 = (hbar / 2) * np.diag([np.exp(-r), np.exp(r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with eng:
            ops.Gaussian(cov) | q

        state = eng.run()
        assert np.allclose(state.cov(), cov, atol=tol)
        assert np.all(len(eng.cmd_applied[0]) == 3)
    def test_covariance_rotated_squeezed(self):
        self.eng.reset()
        q = self.eng.register

        r = 0.1
        phi = 0.2312
        v1 = (self.hbar / 2) * np.diag([np.exp(-r), np.exp(r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with self.eng:
            CovarianceState(cov) | q

        state = self.eng.run(backend=self.backend_name, cutoff_dim=self.D)
        self.assertAllAlmostEqual(state.cov(), cov, delta=self.tol)
        self.assertAllEqual(len(self.eng.cmd_applied), 3)
Example #10
0
    def prepare_gaussian_state(self, r, V, modes):
        if isinstance(modes, int):
            modes = [modes]

        # make sure number of modes matches shape of r and V
        N = len(modes)
        if len(r) != 2*N:
            raise ValueError("Length of means vector must be twice the number of modes.")
        if V.shape != (2*N, 2*N):
            raise ValueError("Shape of covariance matrix must be [2N, 2N], where N is the number of modes.")

        # convert xp-ordering to symmetric ordering
        means = vstack([r[:N], r[N:]]).reshape(-1, order='F')
        C = changebasis(N)
        cov = C @ V @ C.T

        self.circuit.fromscovmat(cov, modes)
        self.circuit.fromsmean(means, modes)
Example #11
0
    def test_rotated_squeezed(self, setup_eng, cutoff, hbar, tol):
        eng, q = setup_eng(3)

        r = 0.1
        phi = 0.2312
        in_state = squeezed_state(r, phi, basis="fock", fock_dim=cutoff)

        v1 = (hbar / 2) * np.diag([np.exp(-2 * r), np.exp(2 * r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with eng:
            ops.Gaussian(cov) | q

        state = eng.run()
        assert len(eng.cmd_applied[0]) == 3
        for n in range(3):
            assert np.allclose(state.fidelity(in_state, n), 1, atol=tol)
Example #12
0
    def test_covariance_rotated_squeezed(self):
        self.logTestName()
        q = self.eng.register

        r = 0.1
        phi = 0.2312
        in_state = squeezed_state(r, phi, basis='fock', fock_dim=self.D)

        v1 = (self.hbar / 2) * np.diag([np.exp(-2 * r), np.exp(2 * r)])
        A = changebasis(3)
        cov = A.T @ block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3) @ A

        with self.eng:
            Gaussian(cov) | q

        state = self.eng.run(**self.kwargs)
        self.assertAllEqual(len(self.eng.cmd_applied[0]), 3)
        for n in range(3):
            self.assertAllAlmostEqual(state.fidelity(in_state, n),
                                      1,
                                      delta=self.tol)
Example #13
0
    def test_three_mode_arbitrary(self, setup_backend, pure, hbar, tol):
        """Test that the correct result is returned for an arbitrary quadratic polynomial"""
        backend = setup_backend(3)
        # increase the cutoff to 7 for accuracy
        backend.reset(cutoff_dim=7, pure=pure)

        # fmt:off
        A = np.array([[
            0.7086495, -0.39299695, 0.30536448, 0.48822049, 0.64987373,
            0.7020327
        ],
                      [
                          -0.39299695, 0.0284145, 0.53202656, 0.20232385,
                          0.26288656, 0.20772833
                      ],
                      [
                          0.30536448, 0.53202656, 0.28126466, 0.64192545,
                          -0.36583748, 0.51704656
                      ],
                      [
                          0.48822049, 0.20232385, 0.64192545, 0.51033017,
                          0.29129713, 0.77103581
                      ],
                      [
                          0.64987373, 0.26288656, -0.36583748, 0.29129713,
                          0.37646972, 0.2383589
                      ],
                      [
                          0.7020327, 0.20772833, 0.51704656, 0.77103581,
                          0.2383589, -0.96494418
                      ]])

        # fmt:on
        d = np.array([
            0.71785224, -0.80064627, 0.08799823, 0.76189805, 0.99665321,
            -0.60777437
        ])
        k = 0.123

        a_list = [0.044 + 0.023j, 0.0432 + 0.123j, -0.12 + 0.04j]
        r_list = [0.1065, 0.032, -0.123]
        phi_list = [0.897, 0.31, 0.432]

        mu = np.zeros([6])
        cov = np.zeros([6, 6])

        # squeeze and displace each mode
        for i, (a_, r_, phi_) in enumerate(zip(a_list, r_list, phi_list)):
            backend.prepare_displaced_squeezed_state(np.abs(a_), np.angle(a_),
                                                     r_, phi_, i)
            mu[2 * i:2 * i + 2] = (R(qphi).T @ np.array([a_.real, a_.imag]) *
                                   np.sqrt(2 * hbar))
            cov[2 * i:2 * i + 2, 2 * i:2 * i + 2] = (
                R(qphi).T @ utils.squeezed_cov(r_, phi_, hbar=hbar) @ R(qphi))

        # apply a beamsplitter to the modes
        backend.beamsplitter(np.pi / 4, 0.0, 0, 1)
        backend.beamsplitter(np.pi / 4, 0.0, 1, 2)

        state = backend.state()
        mean, var = state.poly_quad_expectation(A, d, k, phi=qphi)

        # apply a beamsplitter to vector of means and covariance matrices
        t = 1 / np.sqrt(2)
        BS = np.array([[t, 0, -t, 0], [0, t, 0, -t], [t, 0, t, 0],
                       [0, t, 0, t]])

        S1 = block_diag(BS, np.identity(2))
        S2 = block_diag(np.identity(2), BS)

        C = changebasis(3)
        mu = C.T @ S2 @ S1 @ mu
        cov = C.T @ S2 @ S1 @ cov @ S1.T @ S2.T @ C

        modes = list(np.arange(6).reshape(2, -1).T)

        mean_ex = np.trace(A @ cov) + mu @ A @ mu + mu @ d + k
        var_ex = (2 * np.trace(A @ cov @ A @ cov) +
                  4 * mu.T @ A.T @ cov @ A @ mu + d.T @ cov @ d +
                  2 * mu.T @ A.T @ cov @ d + 2 * d.T @ cov @ A @ mu - np.sum([
                      np.linalg.det(hbar * A[:, m][n]) for m in modes
                      for n in modes
                  ]))

        assert np.allclose(mean, mean_ex, atol=tol, rtol=0)
        assert np.allclose(var, var_ex, atol=tol, rtol=0)