def test_qr(): for shape in [(4, 4), (6, 8), (8, 6)]: tol = shape[0] * shape[1] * 100 for qtotal_A in [None, [1]]: A = random_Array(shape, chinfo3, qtotal=qtotal_A, sort=False) A_flat = A.to_ndarray() for qtotal_Q in [None, [1]]: for mode in ['reduced', 'complete']: for qconj in [+1, -1]: for pos in [False, True]: print( f"shape={shape!s} qtot_A={qtotal_A!s} qtot_Q={qtotal_Q!s}" f"mode={mode!s} pos_diag_R={pos!s} inner_qconj={qconj:+d}" ) Q, R = npc.qr(A, mode=mode, pos_diag_R=pos, qtotal_Q=qtotal_Q, inner_qconj=qconj) # print(q._qdata) Q.test_sanity() R.test_sanity() assert np.all( Q.qtotal) == A.chinfo.make_valid(qtotal_Q) assert R.legs[0].qconj == qconj QR = npc.tensordot(Q, R, axes=1) npt.assert_array_almost_equal_nulp( A_flat, QR.to_ndarray(), tol) QdaggerQ = npc.tensordot(Q.conj(), Q, axes=[0, 0]) assert npc.norm(QdaggerQ - npc.eye_like(QdaggerQ)) < 1.e-10
def test_npc_grid_outer(): ci = chinfo3 p_leg = gen_random_legcharge(ci, 4) legs_op = [p_leg, p_leg.conj()] op_0 = 1.j * npc.Array.from_func(np.random.random, legs_op, qtotal=[0], shape_kw='size') op_pl = npc.Array.from_func(np.random.random, legs_op, qtotal=[1], shape_kw='size') op_min = npc.Array.from_func(np.random.random, legs_op, qtotal=[-1], shape_kw='size') op_id = npc.eye_like(op_0) grid = [[op_id, op_pl, op_min, op_0, None], [None, None, None, None, op_min], [None, None, None, None, op_pl], [None, None, None, None, op_0], [None, None, None, None, op_id]] # yapf: disable leg_WL = npc.LegCharge.from_qflat(ci, ci.make_valid([[0], [1], [-1], [0], [0]])) leg_WR = npc.LegCharge.from_qflat(ci, ci.make_valid([[0], [1], [-1], [0], [0]]), -1) leg_WR_calc = npc.detect_grid_outer_legcharge(grid, [leg_WL, None], qconj=-1)[1] leg_WR.test_equal(leg_WR_calc) W = npc.grid_outer(grid, [leg_WL, leg_WR]) W.test_sanity() Wflat = np.zeros([5, 5, 4, 4], dtype=W.dtype) for idx, op in [[(0, 0), op_id], [(0, 1), op_pl], [(0, 2), op_min], [(0, 3), op_0], [(1, 4), op_min], [(2, 4), op_pl], [(3, 4), op_0], [(4, 4), op_id]]: Wflat[idx] = op.to_ndarray() npt.assert_equal(W.to_ndarray(), Wflat)
def test_renyi_disentangler(L=4, eps=1.e-15): xxz_pars = dict(L=L, Jxx=1., Jz=3., hz=0., bc_MPS='finite') M = XXZChain(xxz_pars) psi = purification_mps.PurificationMPS.from_infiniteT(M.lat.mps_sites(), bc='finite') eng = PurificationTEBD(psi, M, {'verbose': 30, 'disentangle': 'renyi'}) theta = eng.psi.get_theta(1, 2) print(theta[0, :, :, 0, :, :]) # find random unitary: SVD of random matix pleg = psi.sites[0].leg pipe = npc.LegPipe([pleg, pleg]) A = npc.Array.from_func_square(rmat.CUE, pipe).split_legs() A.iset_leg_labels(['p0', 'p1', 'p0*', 'p1*']) # Now we have unitary `A`, i.e. the optimal `U` should be `A^dagger`. theta = npc.tensordot(A, theta, axes=[['p0*', 'p1*'], ['p0', 'p1']]) U0 = npc.outer( npc.eye_like(theta, 'q0').iset_leg_labels(['q0', 'q0*']), npc.eye_like(theta, 'q1').iset_leg_labels(['q1', 'q1*'])) U = U0 Sold = np.inf for i in range(20): S, U = eng.used_disentangler.iter(theta, U) if i == 0: S_0 = S print("iteration {i:d}: S={S:.5f}, DS={DS:.4e} ".format(i=i, S=S, DS=Sold - S)) if abs(Sold - S) < eps: print("break: S converged down to {eps:.1e}".format(eps=eps)) break Sold, S = S, Sold else: print("maximum number of iterations reached") theta = npc.tensordot(U, theta, axes=[['q0*', 'q1*'], ['q0', 'q1']]) print("new theta = ") print(theta.itranspose(['vL', 'vR', 'p0', 'q0', 'p1', 'q1'])) print(theta[0, 0]) assert (S < S_0) # this should always be true... if S > 100 * eps: print("final S =", S) warnings.warn("test of purification failed to find the optimum.")
def test_random_matrix_CUE(): for size in [1, 3, 4]: a = rmat.CUE((size, size)) print(a) assert (a.dtype == np.complex) npt.assert_allclose(np.dot(a, a.T.conj()), np.eye(size), EPS, EPS) b = npc.Array.from_func_square(rmat.CUE, leg) b.test_sanity() assert (b.dtype == np.complex) print("b =", b) id = npc.eye_like(b) assert (npc.norm(npc.tensordot(b, b.conj().itranspose(), axes=[1, 0]) - id) < EPS) assert (npc.norm(npc.tensordot(b.conj().itranspose(), b, axes=[1, 0]) - id) < EPS)
def test_random_matrix_U_close_1(): for x in [0., 0.001]: for size in [1, 3, 4]: a = rmat.U_close_1((size, size), x) print(a) assert (a.dtype == np.complex) npt.assert_allclose(np.dot(a, a.T.conj()), np.eye(size), EPS, EPS) npt.assert_allclose(a, np.eye(size), 10 * x, 10 * x + EPS) # not exact for x=0! b = npc.Array.from_func_square(rmat.U_close_1, leg, func_args=[x]) b.test_sanity() assert (b.dtype == np.complex) print("b =", b) id = npc.eye_like(b) assert (npc.norm(npc.tensordot(b, b.conj().itranspose(), axes=[1, 0]) - id) < EPS) assert (npc.norm(npc.tensordot(b.conj().itranspose(), b, axes=[1, 0]) - id) < EPS) assert (npc.norm(b - id) <= 10 * x + EPS) # not exact for x=0!
# p* # | # ^ # | # wL ->--W-->- wR # | # ^ # | # p # create physical spin-1/2 operators Sz, S+, S- Sz = npc.Array.from_ndarray([[0.5, 0.], [0., -0.5]], [p_leg, p_leg.conj()]) Sp = npc.Array.from_ndarray([[0., 1.], [0., 0.]], [p_leg, p_leg.conj()]) Sm = npc.Array.from_ndarray([[0., 0.], [1., 0.]], [p_leg, p_leg.conj()]) Id = npc.eye_like(Sz) # identity for op in [Sz, Sp, Sm, Id]: op.iset_leg_labels(['p', 'p*']) # physical in, physical out mpo_leg = npc.LegCharge.from_qflat(chinfo, [[0], [2], [-2], [0], [0]]) W_grid = [[Id, Sp, Sm, Sz, None ], [None, None, None, None, 0.5 * Jxx * Sm], [None, None, None, None, 0.5 * Jxx * Sp], [None, None, None, None, Jz * Sz ], [None, None, None, None, Id ]] # yapf:disable W = npc.grid_outer(W_grid, [mpo_leg, mpo_leg.conj()]) W.iset_leg_labels(['wL', 'wR', 'p', 'p*']) # wL/wR = virtual left/right of the MPO Ws = [W] * L
def test_MPOTransferMatrix(eps=1.e-13): s = spin_half # exponential decay in Sz term to make it harder gamma = 0.5 Jxy, Jz = 4., 1. hz = 0. grid = [[s.Id, s.Sp, s.Sm, s.Sz, hz * s.Sz], [None, None, None, None, Jxy*0.5*s.Sm], [None, None, None, None, Jxy*0.5*s.Sp], [None, None, None, gamma*s.Id, Jz*s.Sz], [None, None, None, None, s.Id]] # yapf: disable H = mpo.MPO.from_grids([s] * 3, [grid] * 3, 'infinite', 0, 4, max_range=np.inf) psi = mps.MPS.from_singlets(s, 3, [(0, 1)], lonely=[2], bc='infinite') psi.roll_mps_unit_cell( -1) # -> nontrivial chi at the cut between unit cells exact_E = ((-0.25 - 0.25) * Jxy # singlet <0.5*Sp_i Sm_{i+1}> = 0.25 = <0.5*Sm_i Sp_{i+1}> - 0.25 * Jz # singlet <Sz_i Sz_{i+1}> + 1. * (0.25 * gamma**2 / (1. - gamma**3)) ) # exponentially decaying "lonely" states # lonely: <Sz_{i} gamma gamma Sz_{i+2} exact_E = exact_E / psi.L # energy per site for transpose in [False, True]: print(f"transpose={transpose!s}") TM = mpo.MPOTransferMatrix(H, psi, transpose=transpose) TM.matvec(TM.guess, project=False) TM.matvec(TM.guess, project=True) val, vec = TM.dominant_eigenvector() assert abs(val - 1.) < eps E0 = TM.energy(vec) print(E0, exact_E) assert abs(E0 - exact_E) < eps if not transpose: vec.itranspose(['vL', 'wL', 'vL*']) assert (vec[:, 4, :] - npc.eye_like(vec, 0)).norm() < eps else: vec.itranspose(['vR*', 'wR', 'vR']) assert (vec[:, 0, :] - npc.eye_like(vec, 0)).norm() < eps # get non-trivial psi psi.perturb( { 'N_steps': 10, 'trunc_params': { 'chi_max': 3, 'svd_min': 1.e-14 } }, close_1=False, canonicalize=False) psi.canonical_form_infinite2() # now find eigenvector again # and check TM |vec> = |vec> + val * |v0> # with |v0> = eye(chi) * IdL/IdR for transpose in [False, True]: print(f"transpose={transpose!s}") TM = mpo.MPOTransferMatrix(H, psi, transpose=transpose) val, vec = TM.dominant_eigenvector() E0 = TM.energy(vec) assert abs(val - 1.) < eps if not transpose: vec.itranspose(['vL', 'wL', 'vL*']) assert (vec[:, 4, :] - npc.eye_like(vec, 0)).norm() < eps v0 = npc.eye_like(vec, 0, labels=['vL', 'vL*']).add_leg(vec.get_leg('wL'), 0, 1, 'wL') else: vec.itranspose(['vR*', 'wR', 'vR']) assert (vec[:, 0, :] - npc.eye_like(vec, 0)).norm() < eps v0 = npc.eye_like(vec, 0, labels=['vR*', 'vR']).add_leg(vec.get_leg('wR'), 4, 1, 'wR') TM_vec = TM.matvec(vec, project=False) TM_vec.itranspose(vec.get_leg_labels()) assert (TM_vec - (vec + E0 * 3 * v0)).norm() < eps
# | # wL ->--W-->- wR # | # ^ # | # p # create physical spin-1/2 operators Sz, S+, S- Sz = npc.Array.from_ndarray([[0.5, 0.], [0., -0.5]], [p_leg, p_leg.conj()], labels=['p', 'p*']) Sp = npc.Array.from_ndarray([[0., 1.], [0., 0.]], [p_leg, p_leg.conj()], labels=['p', 'p*']) Sm = npc.Array.from_ndarray([[0., 0.], [1., 0.]], [p_leg, p_leg.conj()], labels=['p', 'p*']) Id = npc.eye_like(Sz, labels=Sz.get_leg_labels()) # identity mpo_leg = npc.LegCharge.from_qflat(chinfo, [[0], [2], [-2], [0], [0]]) W_grid = [[Id, Sp, Sm, Sz, None ], [None, None, None, None, 0.5 * Jxx * Sm], [None, None, None, None, 0.5 * Jxx * Sp], [None, None, None, None, Jz * Sz ], [None, None, None, None, Id ]] # yapf:disable W = npc.grid_outer(W_grid, [mpo_leg, mpo_leg.conj()], grid_labels=['wL', 'wR']) # wL/wR = virtual left/right of the MPO Ws = [W] * L print("3) define 'environments' left and right")