def test_stiefel_tangent(self): C = uni.choi(2, 1) TX1 = C.stiefel_tangent() TX2 = C.stiefel_tangent(full=True) self.assertEqual(TX1.shape, (8, 2)) self.assertEqual(TX2.shape, (8, 8)) self.assertEqual(la.norm(TX1 - TX2[:, :2]), 0) C2 = ch.QuantumChannel(la.expm(TX2)[:, :2], 'stiefel') self.assertAlmostEqual(la.norm(C.choi() - C2.choi()), 0) self.assertEqual(C2.rank(), 1) self.assertTrue(C2.is_valid()) C = uni.choi(3, 9) TX1 = C.stiefel_tangent() TX2 = C.stiefel_tangent(full=True) self.assertEqual(TX1.shape, (27, 3)) self.assertEqual(TX2.shape, (27, 27)) self.assertEqual(la.norm(TX1 - TX2[:, :3]), 0) C2 = ch.QuantumChannel(la.expm(TX2)[:, :3], 'stiefel') self.assertAlmostEqual(la.norm(C.choi() - C2.choi()), 0) self.assertEqual(C2.rank(), 9) self.assertTrue(C2.is_valid())
def test_is_extremal(self): U1 = uni.choi(2, 1) self.assertTrue(U1.is_extremal()) U2 = uni.choi(2, 1) self.assertTrue(U2.is_extremal()) mix = np.random.rand() unital_map = ch.QuantumChannel(mix * U1.choi() + (1 - mix) * U2.choi(), 'choi') self.assertFalse(unital_map.is_extremal()) gamma = np.random.rand() amp_damp = ch.QuantumChannel( [[[1, 0], [0, np.sqrt(1 - gamma)]], [[0, np.sqrt(gamma)], [0, 0]]], 'kraus') self.assertTrue(amp_damp.is_extremal()) C3 = uni.choi(2, 3) self.assertFalse(C3.is_extremal()) C4 = uni.choi(2, 4) self.assertFalse(C4.is_extremal())
def test_choi_seed(self): rgen1 = np.random.RandomState(1) choi1 = uniform.choi(2, 4, False, rgen1) rgen2 = np.random.RandomState(1) choi2 = uniform.choi(2, 4, False, rgen2) self.assertEqual(la.norm(choi1 - choi2), 0)
def test_partial_trace(self): ch1 = uni.choi(2) ch2 = uni.choi(2) cht1 = ch1 ^ ch2 self.assertAlmostEqual(np.linalg.norm(ch1.TrA() - ch1.TrA().conj().T), 0) self.assertAlmostEqual(np.linalg.norm(ch1.TrB() - np.eye(2)), 0) self.assertAlmostEqual(np.linalg.norm(cht1.TrB() - np.eye(4)), 0)
def test_kron_n(self): X = uni.choi(2) X3_a = X.kron(3) X3_b = X ^ X ^ X self.assertEqual(la.norm(X3_a.choi() - X3_b.choi()), 0)
def test_choi_as_matrix(self): choi = uniform.choi(3, as_channel=False) self.assertTrue(choi.shape == (9, 9)) self.assertEqual(type(choi), np.ndarray) self.assertEqual(choi.dtype, np.complex128) self.assertTrue(ch.QuantumChannel(choi, 'choi').is_valid())
def test_missing_ptm_paths(self): ptm1 = uni.choi(2).ptm() ptm2 = uni.choi(2).ptm() ch1 = ch.QuantumChannel(ptm1, 'ptm') ch2 = ch.QuantumChannel(ptm2, 'ptm') out = ch1 * ch2 self.assertEqual(np.linalg.norm(ptm1 @ ptm2 - out.ptm()), 0) bv = ptm1 @ (np.eye(4)[:, 1]) bv[0] = 1.0 rho = ch.QuantumState(bv[1:], 'bv') rho_out = ch2 * rho self.assertAlmostEqual( np.linalg.norm((ptm2 @ bv)[1:, np.newaxis] - rho_out.bloch_vector()), 0)
def test_missing_stiefel2(self): ch1 = uni.choi(2) ch2 = ch.QuantumChannel(ch1.stiefel2(), 'stiefel2') self.assertAlmostEqual( np.linalg.norm(ch1.liouvillian() - ch2.liouvillian()), 0) ch2 = ch.QuantumChannel(ch1.stiefel2(), 'stiefel2') for i, k in enumerate(ch1.kraus()): self.assertAlmostEqual(np.linalg.norm(k - ch2.kraus()[i]), 0)
def test_1_qutrit_random_op(self): state = uniform.density_matrix(3) op = uniform.choi(3) out = op*state op2 = ch.QuantumChannel(op.ptm(),'ptm') self.assertAlmostEqual(la.norm(op.choi()-op2.choi()),0,14) bvout = op.ptm()[1:,1:]@state.bloch_vector()+op.ptm()[1:,0,np.newaxis]*1./np.sqrt(2) bvout2 = ch.QuantumState(bvout,'bv') self.assertAlmostEqual(la.norm(out.bloch_vector()-bvout),0,14) self.assertAlmostEqual(la.norm(out.density_matrix()-bvout2.density_matrix()),0,14)
def test_2_qutrit_random_op(self): state = uniform.density_matrix(9) op = uniform.choi(9) out = op*state op2 = ch.QuantumChannel(op.ptm(),'ptm') self.assertAlmostEqual(la.norm(op.choi()-op2.choi()),0,14) #This illustrates the ugliness of wanting a unit sphere bvout = op.ptm()[1:,1:]@state.bloch_vector()+op.ptm()[1:,0,np.newaxis]*1./np.sqrt(8) bvout2 = ch.QuantumState(bvout,'bv') self.assertAlmostEqual(la.norm(out.bloch_vector()-bvout),0,15) self.assertAlmostEqual(la.norm(out.density_matrix()-bvout2.density_matrix()),0,14)
def test_dual(self): D = uni.choi(N=3) DD = D.dual() DDD = DD.dual() self.assertEqual(la.norm(D.choi() - DDD.choi()), 0) P = ch.QuantumChannel(D.ptm(), 'ptm') PP = P.dual() PPP = PP.dual() self.assertEqual(la.norm(P.ptm() - PPP.ptm()), 0) K = ch.QuantumChannel(D.kraus(), 'kraus') KK = K.dual() KKK = KK.dual() self.assertEqual(la.norm(K.stiefel() - KKK.stiefel()), 0) self.assertAlmostEqual(la.norm(DD.choi() - KK.choi()), 0) self.assertAlmostEqual(la.norm(DD.choi() - PP.choi()), 0)
def test_is_valid_gaps(self): ch1 = uni.choi(2) self.assertTrue(ch1.is_valid()) vals, vecs = la.eigh(ch1.choi()) C = vecs @ np.diag(vals * np.array([1, 1, 1, -1])) @ vecs.conj().T C = ch.QuantumChannel(C, 'choi') self.assertFalse(C.is_valid()) C = ch.QuantumChannel(1.1 * ch1.choi(), 'choi') self.assertFalse(C.is_valid()) C = ch.QuantumChannel(ch1.kraus(), 'kraus') self.assertTrue(C.is_valid()) ks = C.kraus() ks[0] += np.random.randn(2, 2) * .02 C = ch.QuantumChannel(ks, 'kraus') self.assertFalse(C.is_valid())
def test_choi_as_channel(self): choi = uniform.choi(2) self.assertTrue(choi.is_valid())
def test_rank_choi(self): for i in range(1, 10): choi = uniform.choi(3, i) self.assertTrue(choi.rank() == i)
def test_2_qutrit_ptm_O(self): U = uniform.choi(N=9,rank=1) self.assertAlmostEqual(np.abs(la.det(U.ptm()[1:,1:])),1.0,10)