def test_basic(self, rand_rank): rho = qu.rand_rho(9) ln = qu.logneg(rho, [3, 3]) for p in (0.2, 0.5, 0.8, 1.0): rho_d = qu.dephase(rho, p, rand_rank=rand_rank) assert qu.logneg(rho_d, [3, 3]) <= ln assert rho_d.tr() == pytest.approx(1.0)
def test_subsystem(self): p = qu.singlet_pairs(4) rhoab = p.ptr([2, 2, 2, 2], [0, 1]) assert qu.logneg(rhoab, [2] * 2) > 1 - 1e-14 rhoab = p.ptr([2, 2, 2, 2], [1, 2]) assert qu.logneg(rhoab, [2] * 2) < 1e-14 rhoab = p.ptr([2, 2, 2, 2], [2, 3]) assert qu.logneg(rhoab, [2] * 2) > 1 - 1e-14
def test_entanglement(self): rho = qu.rand_seperable([2, 3, 2], 10) assert_allclose(qu.tr(rho), 1.0) assert qu.isherm(rho) assert qu.logneg(rho, [2, 6]) < 1e-12 assert qu.logneg(rho, [6, 2]) < 1e-12 rho_a = qu.ptr(rho, [2, 3, 2], 1) el = qu.eigvalsh(rho_a) assert np.all(el < 1 - 1e-12) assert np.all(el > 1e-12)
def test_entanglement(self): rho = rand_seperable([2, 3, 2], 10) assert_almost_equal(tr(rho), 1.0) assert isherm(rho) assert logneg(rho, [2, 6]) < 1e-12 assert logneg(rho, [6, 2]) < 1e-12 rho_a = ptr(rho, [2, 3, 2], 1) el = eigvals(rho_a) assert np.all(el < 1 - 1e-12) assert np.all(el > 1e-12)
def test_quevo_multi_compute(self, method, qtype): ham = ham_heis(2, cyclic=False) p0 = qu(up() & down(), qtype=qtype) def some_quantity(t, _): return t def some_other_quantity(_, pt): return logneg(pt) evo = QuEvo(p0, ham, method=method, compute={ 't': some_quantity, 'logneg': some_other_quantity }) manual_lns = [] for pt in evo.at_times(np.linspace(0, 1, 6)): manual_lns.append(logneg(pt)) ts = evo.results['t'] lns = evo.results['logneg'] assert len(lns) >= len(manual_lns) # check a specific value of logneg at t=0.8 was computed automatically checked = False for t, ln in zip(ts, lns): if abs(t - 0.8) < 1e-12: assert abs(ln - manual_lns[4]) < 1e-12 checked = True assert checked
def test_logneg_approx_many_body(self, psi_mb_abc, bsz): sysa = [0, 1, 7, 8] sysb = [2, 3, 9] rho_ab = psi_mb_abc.ptr(DIMS_MB, sysa + sysb) actual_ln = logneg(rho_ab, [2] * 7, sysa=(0, 1, 4, 5)) approx_ln = logneg_subsys_approx(psi_mb_abc, DIMS_MB, sysa=sysa, sysb=sysb, bsz=bsz) assert_allclose(actual_ln, approx_ln, rtol=1e-1)
def test_bipartite_schmidt_state(self): psi = MPS_rand_state(16, 5) psid = psi.to_dense() eln = qu.logneg(psid, [2**7, 2**9]) s_d_ket = psi.bipartite_schmidt_state(7, get='ket-dense') ln_d_ket = qu.logneg(s_d_ket, [5, 5]) assert_allclose(eln, ln_d_ket, rtol=1e-5) s_d_rho = psi.bipartite_schmidt_state(7, get='rho-dense') ln_d_rho = qu.logneg(s_d_rho, [5, 5]) assert_allclose(eln, ln_d_rho, rtol=1e-5) T_s_ket = psi.bipartite_schmidt_state(7, get='ket') assert set(T_s_ket.inds) == {'kA', 'kB'} assert_allclose(T_s_ket.H @ T_s_ket, 1.0) T_s_rho = psi.bipartite_schmidt_state(7, get='rho') assert set(T_s_rho.outer_inds()) == {'kA', 'kB', 'bA', 'bB'} assert_allclose(T_s_rho.H @ T_s_rho, 1.0)
def test_logneg_subsys_pure(self): p = qu.rand_ket(2**(3 + 4)) dims = (2**3, 2**4) sysa = 0 sysb = 1 # exact 1 ln0 = qu.logneg(p, dims, 0) # exact 2 ln1 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1e30) assert_allclose(ln0, ln1) # approx ln2 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1, tol=5e-3) assert ln1 != ln2 assert_allclose(ln1, ln2, rtol=1e-1)
def test_logneg_subsys_pure_should_swap_subsys(self): p = qu.rand_ket(2**(5 + 2)) dims = (2**5, 2**2) sysa = 0 sysb = 1 # exact 1 ln0 = qu.logneg(p, dims, 0) # exact 2 ln1 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1e30) assert_allclose(ln0, ln1) # approx ln2 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1, tol=0.005) assert ln1 != ln2 assert_allclose(ln1, ln2, rtol=0.2)
def test_logneg_subsys(self): p = qu.rand_ket(2**(2 + 3 + 1 + 2)) dims = (2**2, 2**3, 2**1, 2**2) sysa = [0, 3] sysb = 1 # exact 1 ln0 = qu.logneg(qu.ptr(p, dims, [0, 1, 3]), [4, 8, 4], [0, 2]) # exact 2 ln1 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1e30) assert_allclose(ln0, ln1) # approx ln2 = qu.logneg_subsys(p, dims, sysa, sysb, approx_thresh=1) assert ln1 != ln2 assert_allclose(ln1, ln2, rtol=5e-2)
def test_quevo_compute_callback(self, qtype, method): ham = ham_heis(2, cyclic=False) p0 = qu(up() & down(), qtype=qtype) def some_quantity(t, pt): return t, logneg(pt) evo = QuEvo(p0, ham, method=method, compute=some_quantity) manual_lns = [] for pt in evo.at_times(np.linspace(0, 1, 6)): manual_lns.append(logneg(pt)) ts, lns = zip(*evo.results) assert len(lns) >= len(manual_lns) # check a specific value of logneg at t=0.8 was computed automatically checked = False for t, ln in zip(ts, lns): if abs(t - 0.8) < 1e-12: assert abs(ln - manual_lns[4]) < 1e-12 checked = True assert checked
def test_evo_multi_compute(self, method, qtype): ham = qu.ham_heis(2, cyclic=False) p0 = qu.qu(qu.up() & qu.down(), qtype=qtype) def some_quantity(t, _): return t def some_other_quantity(_, pt): return qu.logneg(pt) # check that hamiltonian gets accepted without error for all methods def some_other_quantity_accepting_ham(t, pt, H): return qu.logneg(pt) compute = { 't': some_quantity, 'logneg': some_other_quantity, 'logneg_ham': some_other_quantity_accepting_ham } evo = qu.Evolution(p0, ham, method=method, compute=compute) manual_lns = [] for pt in evo.at_times(np.linspace(0, 1, 6)): manual_lns.append(qu.logneg(pt)) ts = evo.results['t'] lns = evo.results['logneg'] lns_ham = evo.results['logneg_ham'] assert len(lns) >= len(manual_lns) # check a specific value of logneg at t=0.8 was computed automatically checked = False for t, ln, ln_ham in zip(ts, lns, lns_ham): if abs(t - 0.8) < 1e-12: assert abs(ln - manual_lns[4]) < 1e-12 # check that accepting hamiltonian didn't mess it up assert ln == ln_ham checked = True assert checked
def test_logneg_approx_simple(self, psi_abc, bsz): rho_ab = psi_abc.ptr(DIMS, [0, 1]) actual_ln = logneg(rho_ab, DIMS[:-1], 0) approx_ln = logneg_subsys_approx(psi_abc, DIMS, 0, 1, bsz=bsz) assert_allclose(actual_ln, approx_ln, rtol=2e-1)
def test_bell_states(self, qtype, bs): p = qu.bell_state(bs, qtype=qtype) assert qu.logneg(p) > 1.0 - 1e-14
def some_quantity(t, pt): return t, logneg(pt)
def some_other_quantity(_, pt): return logneg(pt)
def test_interleaving(self): p = permute(singlet() & singlet(), [2, 2, 2, 2], [0, 2, 1, 3]) assert logneg(p, [2] * 4, sysa=[0, 3]) > 2 - 1e-13
def some_other_quantity_accepting_ham(t, pt, H): return qu.logneg(pt)
def test_interleaving(self): p = qu.permute(qu.singlet() & qu.singlet(), [2, 2, 2, 2], [0, 2, 1, 3]) assert qu.logneg(p, [2] * 4, sysa=[0, 3]) > 2 - 1e-13