def random_cov(num_modes=200, pure=False, nonclassical=True): r"""Creates a random covariance matrix for testing. Args: num_modes (int): number of modes pure (bool): Gaussian state is pure nonclassical (bool): Gaussian state is nonclassical Returns: (array): a covariance matrix """ M = num_modes O = interferometer(random_interferometer(M)) eta = 1 if pure else 0.123 r = 1.234 if nonclassical: # squeezed inputs cov_in = np.diag(np.concatenate([np.exp(2 * r) * np.ones(M), np.exp(-2 * r) * np.ones(M)])) elif not nonclassical and pure: # vacuum inputs cov_in = np.eye(2 * M) elif not nonclassical and not pure: # squashed inputs cov_in = np.diag(np.concatenate([np.exp(2 * r) * np.ones(M), np.ones(M)])) cov_out = O @ cov_in @ O.T _, cov = passive_transformation( np.zeros([len(cov_out)]), cov_out, np.sqrt(eta) * np.identity(len(cov_out) // 2) ) return cov
def test_transformation(self, tol): """Test that an transformation returns the correct state""" M = 4 cov = np.arange(4 * M**2, dtype=np.float64).reshape((2 * M, 2 * M)) mu = np.arange(2 * M, dtype=np.float64) T = np.sqrt(0.9) * M**(-0.5) * np.ones((6, M), dtype=np.float64) mu_out, cov_out = symplectic.passive_transformation(mu, cov, T) # fmt:off expected_mu = np.array([ 2.84604989, 2.84604989, 2.84604989, 2.84604989, 2.84604989, 2.84604989, 10.43551628, 10.43551628, 10.43551628, 10.43551628, 10.43551628, 10.43551628 ]) expected_cov = np.array([ [48.7, 47.7, 47.7, 47.7, 47.7, 47.7, 63., 63., 63., 63., 63., 63.], [47.7, 48.7, 47.7, 47.7, 47.7, 47.7, 63., 63., 63., 63., 63., 63.], [47.7, 47.7, 48.7, 47.7, 47.7, 47.7, 63., 63., 63., 63., 63., 63.], [47.7, 47.7, 47.7, 48.7, 47.7, 47.7, 63., 63., 63., 63., 63., 63.], [47.7, 47.7, 47.7, 47.7, 48.7, 47.7, 63., 63., 63., 63., 63., 63.], [47.7, 47.7, 47.7, 47.7, 47.7, 48.7, 63., 63., 63., 63., 63., 63.], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 178.3, 177.3, 177.3, 177.3, 177.3, 177.3 ], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 177.3, 178.3, 177.3, 177.3, 177.3, 177.3 ], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 177.3, 177.3, 178.3, 177.3, 177.3, 177.3 ], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 177.3, 177.3, 177.3, 178.3, 177.3, 177.3 ], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 177.3, 177.3, 177.3, 177.3, 178.3, 177.3 ], [ 163.8, 163.8, 163.8, 163.8, 163.8, 163.8, 177.3, 177.3, 177.3, 177.3, 177.3, 178.3 ] ]) # fmt:on assert np.allclose(mu_out, expected_mu, atol=tol, rtol=0) assert np.allclose(cov_out, expected_cov, atol=tol, rtol=0)
def test_hbar(self, hbar, tol): """test that the output is a valid covariance matrix, even when not square""" M = 4 a = np.arange(4 * M**2, dtype=np.float64).reshape((2 * M, 2 * M)) cov = a @ a.T + np.eye(2 * M) mu = np.arange(2 * M, dtype=np.float64) T = np.sqrt(0.9) * M**(-0.5) * np.ones((6, M), dtype=np.float64) _, cov_out = symplectic.passive_transformation(mu, cov, T, hbar=hbar) assert is_valid_cov(cov_out, hbar=hbar, atol=tol, rtol=0)
def test_valid_cov(self, M, tol): """test that the output is a valid covariance matrix, even when not square""" a = np.arange(4 * M**2, dtype=np.float64).reshape((2 * M, 2 * M)) cov = a @ a.T + np.eye(2 * M) mu = np.arange(2 * M, dtype=np.float64) T = np.sqrt(0.9) * M**(-0.5) * np.ones((6, M), dtype=np.float64) mu_out, cov_out = symplectic.passive_transformation(mu, cov, T) assert cov_out.shape == (12, 12) assert len(mu_out) == 12 assert is_valid_cov(cov_out, atol=tol, rtol=0)
def test_log_negativity_two_modes(r, etaA, etaB, hbar): """Tests the log_negativity for two modes states following Eq. 13 of https://arxiv.org/pdf/quant-ph/0506124.pdf""" cov = (hbar / 2) * two_mode_squeezing(2 * r, 0) _, cov_lossy = passive_transformation(np.zeros([4]), cov, np.diag([etaA, etaB]), hbar=hbar) cov_xpxp = xxpp_to_xpxp(cov_lossy) / (hbar / 2) alpha = cov_xpxp[:2, :2] gamma = cov_xpxp[2:, :2] beta = cov_xpxp[2:, 2:] invariant = np.linalg.det(alpha) + np.linalg.det(beta) - 2 * np.linalg.det(gamma) detcov = np.linalg.det(cov_xpxp) expected = -np.log(np.sqrt((invariant - np.sqrt(invariant**2 - 4 * detcov)) / 2)) obtained = log_negativity(cov_lossy, modes_A=[0], hbar=hbar) assert np.allclose(expected, obtained)
def test_unitary(self, M, tol): """ test that the outputs agree with the interferometer class when transformation is unitary """ a = np.arange(4 * M**2, dtype=np.float64).reshape((2 * M, 2 * M)) cov = a @ a.T + np.eye(2 * M) mu = np.arange(2 * M, dtype=np.float64) U = M**(-0.5) * np.fft.fft(np.eye(M)) S_U = symplectic.interferometer(U) cov_U = S_U @ cov @ S_U.T mu_U = S_U @ mu mu_T, cov_T = symplectic.passive_transformation(mu, cov, U) assert np.allclose(mu_U, mu_T, atol=tol, rtol=0) assert np.allclose(cov_U, cov_T, atol=tol, rtol=0)