def test_functional_inverse(self, dim): """Check that xxpp_to_xpxp is the inverse of xpxp_to_xxpp and viceversa""" M = np.random.rand(dim, dim) assert np.all(M == symplectic.xxpp_to_xpxp(symplectic.xpxp_to_xxpp(M))) assert np.all(M == symplectic.xpxp_to_xxpp(symplectic.xxpp_to_xpxp(M))) v = np.random.rand(dim) assert np.all(v == symplectic.xxpp_to_xpxp(symplectic.xpxp_to_xxpp(v))) assert np.all(v == symplectic.xpxp_to_xxpp(symplectic.xxpp_to_xpxp(v)))
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") cov = xxpp_to_xpxp(V) self.circuit.from_covmat(cov, modes) self.circuit.from_mean(means, modes)
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.""" means_xp = np.array([1, 2, 3, 4, 5, 6]) means_symmetric = np.array([1, 4, 2, 5, 3, 6]) assert np.all(symplectic.xxpp_to_xpxp(means_xp) == means_symmetric) assert np.all(symplectic.xpxp_to_xxpp(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.""" 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(symplectic.xxpp_to_xpxp(cov_xp) == cov_symmetric) assert np.all(symplectic.xpxp_to_xxpp(cov_symmetric) == cov_xp)
def test_thermal(self, setup_eng, hbar, tol): """Testing a thermal state""" eng, prog = setup_eng(3) cov = np.diag(hbar * (np.array([0.3, 0.4, 0.2] * 2) + 0.5)) with prog.context as q: ops.Gaussian(cov, decomp=False) | q state = eng.run(prog).state indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:, indices][indices, :] assert np.allclose(state.covs(), np.expand_dims(cov, axis=0), atol=tol)
def test_squeezed(self, setup_eng, hbar, tol): """Testing a squeezed state""" eng, prog = setup_eng(3) cov = (hbar / 2) * np.diag([np.exp(-0.1)] * 3 + [np.exp(0.1)] * 3) with prog.context as q: ops.Gaussian(cov, decomp=False) | q state = eng.run(prog).state indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:, indices][indices, :] assert np.allclose(state.covs(), np.expand_dims(cov, axis=0), atol=tol)
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_vacuum(self, setup_eng, hbar, tol): """Testing a vacuum state""" eng, prog = setup_eng(3) cov = (hbar / 2) * np.identity(6) with prog.context as q: ops.Gaussian(cov, decomp=False) | q state = eng.run(prog).state indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:, indices][indices, :] assert np.allclose(state.covs(), np.expand_dims(cov, axis=0), atol=tol) assert np.all(state.means() == np.zeros((1, 6))) assert np.allclose(state.fidelity_vacuum(), 1, atol=tol)
def test_CXgate(self, setup_eng, pure, hbar, tol): """Test the action of the CX gate in phase space""" if not pure: pytest.skip("Test only runs on pure states") N = 2 eng, prog = setup_eng(N) r = 3 x1 = 2 x2 = 1 p1 = 1.37 p2 = 2.71 s = 0.5 with prog.context as q: ops.Sgate(r) | q[0] ops.Xgate(x1) | q[0] ops.Zgate(p1) | q[0] ops.Sgate(r) | q[1] ops.Xgate(x2) | q[1] ops.Zgate(p2) | q[1] ops.CXgate(s) | q state = eng.run(prog).state CXmat = np.array([[1, 0, 0, 0], [s, 1, 0, 0], [0, 0, 1, -s], [0, 0, 0, 1]]) Vexpected = 0.5 * hbar * CXmat @ np.diag( np.exp([-2 * r, -2 * r, 2 * r, 2 * r])) @ CXmat.T rexpected = CXmat @ np.array([x1, x2, p1, p2]) # Check the covariance and mean transformed correctly if eng.backend_name == "gaussian": assert np.allclose(state.cov(), Vexpected, atol=tol, rtol=0) assert np.allclose(state.means(), rexpected, atol=tol, rtol=0) elif eng.backend_name == "bosonic": indices = xxpp_to_xpxp(np.arange(2 * 2)) Vexpected = Vexpected[:, indices][indices, :] rexpected = rexpected[indices] assert np.allclose(state.covs(), np.expand_dims(Vexpected, axis=0), atol=tol, rtol=0) assert np.allclose(state.means(), np.expand_dims(rexpected, axis=0), atol=tol, rtol=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)]) cov = xpxp_to_xxpp(block_diag(*[rot(phi) @ v1 @ rot(phi).T] * 3)) with prog.context as q: ops.Gaussian(cov, decomp=False) | q state = eng.run(prog).state indices = xxpp_to_xpxp(np.arange(2 * 3)) cov = cov[:, indices][indices, :] assert np.allclose(state.covs(), np.expand_dims(cov, axis=0), atol=tol)
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") cov = xxpp_to_xpxp(V) self.circuit.fromscovmat(cov, modes) self.circuit.fromsmean(means, modes)
def scovmat(self): """Constructs and returns the symmetric ordered covariance matrix as defined in [1]""" return xxpp_to_xpxp(self.scovmatxp())