Пример #1
0
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
Пример #2
0
def test_lanczos(n=30, k=5, tol=5.e-15):
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg)
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eigh(H_flat)
    E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0]
    qtotal = npc.detect_qtotal(psi0_flat, [leg])

    H_Op = H  # use `matvec` of the array
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)

    E0, psi0, N = lanczos.lanczos(H_Op, psi_init, {'verbose': 1})
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    psi0_H_psi0 = npc.inner(psi0,
                            npc.tensordot(H, psi0, axes=[1, 0]),
                            do_conj=True)
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
    print("<psi0_flat|H_flat|psi0_flat> / E0_flat = ", end=' ')
    print(np.inner(psi0_flat.conj(), np.dot(H_flat, psi0_flat)) / E0_flat)
    ov = np.inner(psi0.to_ndarray().conj(), psi0_flat)
    print("|<psi0|psi0_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)

    # now repeat, but keep orthogonal to original ground state
    # -> should give second eigenvector psi1 in the same charge sector
    for i in range(1, len(E_flat)):
        E1_flat, psi1_flat = E_flat[i], psi_flat[:, i]
        qtotal = npc.detect_qtotal(psi1_flat, psi0.legs)
        if np.all(qtotal == psi0.qtotal):
            break  # found psi1 in same charge sector
    else:
        print(
            "warning: test didn't find a second eigenvector in the same charge sector!"
        )
        return  # just ignore the rest....
    E1, psi1, N = lanczos.lanczos(H_Op,
                                  psi_init, {'verbose': 1},
                                  orthogonal_to=[psi0])
    print("E1 = {E1:.14f} vs exact {E1_flat:.14f}".format(E1=E1,
                                                          E1_flat=E1_flat))
    print("|E1-E1_flat| / |E1_flat| =", abs((E1 - E1_flat) / E1_flat))
    psi1_H_psi1 = npc.inner(psi1,
                            npc.tensordot(H, psi1, axes=[1, 0]),
                            do_conj=True)
    print("<psi1|H|psi1> / E1 = 1 + ", psi1_H_psi1 / E1 - 1.)
    assert (abs(psi1_H_psi1 / E1 - 1.) < tol)
    print("<psi1_flat|H_flat|psi1_flat> / E1_flat = ", end=' ')
    print(np.inner(psi1_flat.conj(), np.dot(H_flat, psi1_flat)) / E1_flat)
    ov = np.inner(psi1.to_ndarray().conj(), psi1_flat)
    print("|<psi1|psi1_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)
    # and finnally check also orthogonality to psi0
    ov = npc.inner(psi0, psi1, do_conj=True)
    print("|<psi0|psi1>| =", abs(ov))
    assert (abs(ov) < tol**0.5)
Пример #3
0
def test_TransferMatrix(chi=4, d=2):
    psi = random_MPS(2, d, chi, bc='infinite', form=None)
    full_TM = npc.tensordot(psi._B[0], psi._B[0].conj(), axes=['p', 'p*'])
    full_TM = npc.tensordot(full_TM, psi._B[1], axes=['vR', 'vL'])
    full_TM = npc.tensordot(full_TM, psi._B[1].conj(), axes=[['vR*', 'p'], ['vL*', 'p*']])
    full_TM = full_TM.combine_legs([['vL', 'vL*'], ['vR', 'vR*']], qconj=[+1, -1])
    full_TM_dense = full_TM.to_ndarray()
    eta_full, w_full = np.linalg.eig(full_TM_dense)
    sort = np.argsort(np.abs(eta_full))[::-1]
    eta_full = eta_full[sort]
    w_full = w_full[:, sort]
    TM = mps.TransferMatrix(psi, psi, charge_sector=0, form=None)
    eta, w = TM.eigenvectors(3)
    print("transfer matrix yields eigenvalues ", eta)
    print(eta.shape, eta_full.shape)
    print(psi.dtype)
    # note: second and third eigenvalue are complex conjugates
    if bool(eta[2].imag > 0.) == bool(eta_full[2].imag > 0.):
        npt.assert_allclose(eta[:3], eta_full[:3])
    else:
        npt.assert_allclose(eta[:3], eta_full[:3].conj())
    # compare largest eigenvector
    w0_full = w_full[:, 0]
    w0 = w[0].to_ndarray()
    assert (abs(np.sum(w0_full)) > 1.e-20)  # should be the case for random stuff
    w0_full /= np.sum(w0_full)  # fixes norm & phase
    w0 /= np.sum(w0)
    npt.assert_allclose(w0, w0_full)
Пример #4
0
    def _swap_disentangle_bond(self, i, swap=True, disentangle=False):
        """swap sites (i-1, i) (if swap = True) """
        # very similar to update_bond
        i0, i1 = i - 1, i
        # Construct the theta matrix
        theta = self.psi.get_theta(i0, n=2)  # 'vL', 'vR', 'p0', 'p1', 'q0', 'q1'
        if swap:
            theta.ireplace_labels(['p0', 'q0', 'p1', 'q1'], ['p1', 'q1', 'p0', 'q0'])
        if disentangle:
            theta, U_disent = self.disentangle(theta)
        theta = theta.combine_legs([('vL', 'p0', 'q0'), ('vR', 'p1', 'q1')], qconj=[+1, -1])

        # Perform the SVD and truncate the wavefunction
        U, S, V, trunc_err, renormalize = svd_theta(theta,
                                                    self.trunc_params,
                                                    inner_labels=['vR', 'vL'])

        # bring back to right-canonical 'B' form and update matrices
        B_R = V.split_legs(1).ireplace_labels(['p1', 'q1'], ['p', 'q'])
        C = self.psi.get_theta(i0, n=2, formL=0.)
        if swap:
            C.ireplace_labels(['p0', 'q0', 'p1', 'q1'], ['p1', 'q1', 'p0', 'q0'])
        if disentangle and U_disent is not None:
            C = npc.tensordot(U_disent, C, axes=[['q0*', 'q1*'], ['q0', 'q1']])
        B_L = npc.tensordot(C.combine_legs(('vR', 'p1', 'q1'), pipes=theta.legs[1]),
                            V.conj(),
                            axes=['(vR.p1.q1)', '(vR*.p1*.q1*)'])
        B_L.ireplace_labels(['vL*', 'p0', 'q0'], ['vR', 'p', 'q'])
        B_L /= renormalize  # re-normalize to <psi|psi> = 1
        self.psi.set_SR(i0, S)
        self.psi.set_B(i0, B_L, form='B')
        self.psi.set_B(i1, B_R, form='B')
        self._trunc_err_bonds[i] = self._trunc_err_bonds[i] + trunc_err
        return trunc_err
Пример #5
0
    def sweep_one(self):

        LP, RP = make_environment(self.psi,
                                  self.H,
                                  N=self.options.get('N_env', 20))
        _theta = self.psi.get_B(0, form='Th')
        W = self.H.get_W(0)
        _C = npc.Array.from_ndarray(
            np.diagflat(self.psi.get_SR(0)),
            [LP.get_leg('vR').conj(),
             RP.get_leg('vL').conj()],
            labels=['vL', 'vR'])

        dt = self.dt * self.dt_scale
        theta, N_t = self.update_theta_h1(LP, RP, _theta, W,
                                          dt)  #time evolve theta with H1
        C, N_C = self.update_s_h0(LP, RP, _C, dt)  # time evolve s with H0

        Cdag = C.conj().itranspose(['vR*',
                                    'vL*']).iset_leg_labels(['vL', 'vR'])
        theta_Cdag = npc.tensordot(theta, Cdag, axes=('vR', 'vL'))
        Cdag_theta = npc.tensordot(Cdag, theta, axes=('vR', 'vL'))
        A = self.calc_A(theta_Cdag)
        B = self.calc_B(Cdag_theta)
        A, B, theta, s = self.gauge_transform(A, B, theta, C)

        self.psi.set_B(0, A, form='A')
        self.psi.set_B(0, theta, form='Th')
        self.psi.set_B(0, B, form='B')
        self.psi.set_SL(0, s)
Пример #6
0
def test_MPO_var(L=8, tol=1.e-13):
    xxz_pars = dict(L=L,
                    Jx=1.,
                    Jy=1.,
                    Jz=1.1,
                    hz=0.1,
                    bc_MPS='finite',
                    conserve=None)
    M = SpinChain(xxz_pars)
    psi = random_MPS(L, 2, 10)
    exp_val = M.H_MPO.expectation_value(psi)

    ED = ExactDiag(M)
    ED.build_full_H_from_mpo()
    psi_full = ED.mps_to_full(psi)
    exp_val_full = npc.inner(psi_full,
                             npc.tensordot(ED.full_H, psi_full, axes=1),
                             axes='range',
                             do_conj=True)
    assert abs(exp_val - exp_val_full) / abs(exp_val_full) < tol

    Hsquared = M.H_MPO.variance(psi, 0.)

    Hsquared_full = npc.inner(psi_full,
                              npc.tensordot(ED.full_H,
                                            npc.tensordot(ED.full_H,
                                                          psi_full,
                                                          axes=1),
                                            axes=1),
                              axes='range',
                              do_conj=True)
    assert abs(Hsquared - Hsquared_full) / abs(Hsquared_full) < tol
    var = M.H_MPO.variance(psi)
    var_full = Hsquared_full - exp_val_full**2
    assert abs(var - var_full) / abs(var_full) < tol
Пример #7
0
def make_uniform(psi):
    _chis = psi.chi

    #RCF
    TB = TransferMatrix(psi, psi, shift_bra=1, shift_ket=0)
    es_B, evs_B = TB.eigenvectors()
    U = evs_B[0].split_legs(['(vL.vL*)']).iset_leg_labels(['vL','vR'])
    _B = psi.get_B(1)
    B = npc.tensordot(_B, U, axes=('vR','vL'))
    B = (B/npc.norm(B))*np.sqrt(_chis[1])

    #LCF
    TA = TransferMatrix(psi, psi, shift_bra=1, shift_ket=0, form='A', transpose=True)
    es_A, evs_A = TA.eigenvectors()
    V = evs_A[0].split_legs(['(vR*.vR)'])
    Vdag = V.conj()
    _A = psi.get_B(1, form='A')
    A = npc.tensordot(_A, Vdag, axes=('vR','vR*'))
    A = (A/npc.norm(A))*np.sqrt(_chis[1])

    s = 0.5*(psi.get_SL(0) + psi.get_SL(1))
    upsi = make_uMPS(psi)
    upsi.set_B(0, A, form='A')
    upsi.set_B(0, B)
    upsi.set_SL(0, s)
    return upsi
Пример #8
0
 def matvec(self, x):
     x = x.split_legs(['(vL.vR)'])
     x = npc.tensordot(self.Lp, x, axes=('vR', 'vL'))
     x = npc.tensordot(x, self.Rp, axes=(['vR', 'wR'], ['vL', 'wL']))
     x = x.transpose(['vR*', 'vL*'])
     x = x.iset_leg_labels(['vL', 'vR'])
     x = x.combine_legs(['vL', 'vR'])
     return (x)
Пример #9
0
def test_eig():
    size = 10
    max_nulp = 10 * size**3
    ci = chinfo3
    l = gen_random_legcharge(ci, size)
    A = npc.Array.from_func(np.random.random, [l, l.conj()],
                            qtotal=None,
                            shape_kw='size')
    print("hermitian A")
    A += A.conj().itranspose()
    Aflat = A.to_ndarray()
    W, V = npc.eigh(A, sort='m>')
    V.test_sanity()
    V_W = V.scale_axis(W, axis=-1)
    recalc = npc.tensordot(V_W, V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(), max_nulp)
    Wflat, Vflat = np.linalg.eigh(Aflat)
    npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp)
    W2 = npc.eigvalsh(A, sort='m>')
    npt.assert_array_almost_equal_nulp(W, W2, max_nulp)

    print("check complex B")
    B = 1.j * npc.Array.from_func(np.random.random, [l, l.conj()],
                                  shape_kw='size')
    B += B.conj().itranspose()
    B = A + B
    Bflat = B.to_ndarray()
    W, V = npc.eigh(B, sort='m>')
    V.test_sanity()
    recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Bflat, recalc.to_ndarray(), max_nulp)
    Wflat, Vflat = np.linalg.eigh(Bflat)
    npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp)

    print("calculate without 'hermitian' knownledge")
    W, V = npc.eig(B, sort='m>')
    assert (np.max(np.abs(W.imag)) < EPS * max_nulp)
    npt.assert_array_almost_equal_nulp(np.sort(W.real), Wflat, max_nulp)

    print("sparse speigs")
    qi = 1
    ch_sect = B.legs[0].get_charge(qi)
    k = min(3, B.legs[0].slices[qi + 1] - B.legs[0].slices[qi])
    Wsp, Vsp = npc.speigs(B, ch_sect, k=k, which='LM')
    for W_i, V_i in zip(Wsp, Vsp):
        V_i.test_sanity()
        diff = npc.tensordot(B, V_i, axes=1) - V_i * W_i
        assert (npc.norm(diff, np.inf) < EPS * max_nulp)

    print("for trivial charges")
    A = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()],
                            shape_kw='size')
    A = A + A.conj().itranspose()
    Aflat = A.to_ndarray()
    W, V = npc.eigh(A)
    recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(),
                                       10 * A.shape[0]**3)
Пример #10
0
 def matvec(self, x):
     x = x.split_legs(['(vL.vR)'])
     x = npc.tensordot(self.Lp, x, axes=('vR', 'vL'))
     x = npc.tensordot(x, self.Rp, axes=(['vR', 'wR'], ['vL', 'wL']))
     #TODO:next line not needed. Since the transpose does not do anything, should not cost anything. Keep for safety ?
     x = x.transpose(['vR*', 'vL*'])
     x = x.iset_leg_labels(['vL', 'vR'])
     x = x.combine_legs(['vL', 'vR'])
     return (x)
Пример #11
0
def test_npc_tensordot():
    for sort in [True, False]:
        print("sort =", sort)
        a = random_Array((10, 12, 15), chinfo3, qtotal=[0], sort=sort)
        aflat = a.to_ndarray()
        legs_b = [l.conj() for l in a.legs[::-1]]
        b = npc.Array.from_func(np.random.random,
                                legs_b,
                                qtotal=[1],
                                shape_kw='size')
        b = b * (
            1 + 1.j
        )  # make second array complex: check that different dtypes work
        bflat = b.to_ndarray()
        print("axes = 1")  # start simple: only one axes
        c = npc.tensordot(a, b, axes=1)
        c.test_sanity()
        a.test_sanity()
        b.test_sanity()
        npt.assert_array_almost_equal_nulp(a.to_ndarray(), aflat, 1)
        npt.assert_array_almost_equal_nulp(b.to_ndarray(), bflat, 1)
        cflat = np.tensordot(aflat, bflat, axes=1)
        npt.assert_array_almost_equal_nulp(c.to_ndarray(), cflat, sum(a.shape))
        print("axes = 2")  # second: more than one axis
        c = npc.tensordot(a, b, axes=([1, 2], [1, 0]))
        a.test_sanity()
        b.test_sanity()
        npt.assert_array_almost_equal_nulp(a.to_ndarray(), aflat, 1)
        npt.assert_array_almost_equal_nulp(b.to_ndarray(), bflat, 1)
        c.test_sanity()
        cflat = np.tensordot(aflat, bflat, axes=([1, 2], [1, 0]))
        npt.assert_array_almost_equal_nulp(c.to_ndarray(), cflat, sum(a.shape))
        for i in range(b.shape[0]):
            b2 = b[i, :, :]
            if b2.stored_blocks > 0:
                break
        b2flat = b2.to_ndarray()
        print("right tensor fully contracted")
        print(a.shape, b2.shape)
        d = npc.tensordot(a, b2, axes=([0, 1], [1, 0]))
        d.test_sanity()
        dflat = np.tensordot(aflat, b2flat, axes=([0, 1], [1, 0]))
        npt.assert_array_almost_equal_nulp(d.to_ndarray(), dflat, sum(a.shape))
        print("left tensor fully contracted")
        d = npc.tensordot(b2, a, axes=([0, 1], [1, 0]))
        d.test_sanity()
        dflat = np.tensordot(b2flat, aflat, axes=([0, 1], [1, 0]))
        npt.assert_array_almost_equal_nulp(d.to_ndarray(), dflat, sum(a.shape))
    # full/no contraction is tested in test_npc_inner/test_npc_outer
    print("for trivial charge")
    a = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()],
                            shape_kw='size')
    aflat = a.to_ndarray()
    b = npc.tensordot(a, a, axes=1)
    bflat = np.tensordot(aflat, aflat, axes=1)
    npt.assert_array_almost_equal_nulp(b.to_ndarray(), bflat, sum(a.shape))
Пример #12
0
 def matvec(self, theta):
     theta = theta.split_legs(['(p.vR.vL)'])
     Lp = self.Lp
     Rp = self.Rp
     x = npc.tensordot(Lp, theta, axes=('vR', 'vL'))
     x = npc.tensordot(x, self.M, axes=(['p', 'wR'], ['p*', 'wL']))
     x = npc.tensordot(x, Rp, axes=(['vR', 'wR'], ['vL', 'wL']))
     x = x.transpose(['p', 'vR*', 'vL*'])
     x = x.iset_leg_labels(['p', 'vL', 'vR'])
     h = x.combine_legs(['p', 'vR', 'vL'])
     return h
Пример #13
0
 def calculate_error_left_right(self, i):
     Lp = self.environment.get_LP(i)
     Rp = self.environment.get_RP(i)
     W = self.H_MPO.get_W(i)
     B = self.psi.get_B(i)
     p_h_phi = npc.tensordot(Lp, W, axes=['wR', 'wL'])
     p_h_phi = npc.tensordot(p_h_phi, Rp, axes=['wR', 'wL'])
     p_h_phi = npc.tensordot(p_h_phi,
                             B,
                             axes=[('p*', 'vR', 'vL'), ('p', 'vL', 'vR')])
     npc.norm(p_h_phi)
Пример #14
0
 def matvec(self, theta):
     theta = theta.split_legs(['(vL.p.vR)'])
     Lp = self.Lp
     Rp = self.Rp
     x = npc.tensordot(Lp, theta, axes=('vR', 'vL'))
     x = npc.tensordot(x, self.W, axes=(['p', 'wR'], ['p*', 'wL']))
     x = npc.tensordot(x, Rp, axes=(['vR', 'wR'], ['vL', 'wL']))
     #TODO:next line not needed. Since the transpose does not do anything, should not cost anything. Keep for safety ?
     x = x.transpose(['vR*', 'p', 'vL*'])
     x = x.iset_leg_labels(['vL', 'p', 'vR'])
     h = x.combine_legs(['vL', 'p', 'vR'])
     return h
Пример #15
0
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)
Пример #16
0
 def matvec(self, theta):
     theta = theta.split_legs(['(vL.p0.p1.vR)'])
     Lp = self.Lp
     Rp = self.Rp
     x = npc.tensordot(Lp, theta, axes=('vR', 'vL'))
     x = npc.tensordot(x, self.H_MPO0, axes=(['p0', 'wR'], ['p*', 'wL']))
     x.ireplace_label('p', 'p0')
     x = npc.tensordot(x, self.H_MPO1, axes=(['p1', 'wR'], ['p*', 'wL']))
     x.ireplace_label('p', 'p1')
     x = npc.tensordot(x, Rp, axes=(['vR', 'wR'], ['vL', 'wL']))
     x.ireplace_label('vL*', 'vR')
     x.ireplace_label('vR*', 'vL')
     h = x.combine_legs(['vL', 'p0', 'p1', 'vR'])
     return h
Пример #17
0
    def __init__(self, model_params):
        model_params = asConfig(model_params, "AKLTModel")
        L = model_params.get('L', 2)
        site = SpinSite(S=1., conserve='Sz')

        # lattice
        bc_MPS = model_params.get('bc_MPS', 'finite')
        bc = 'open' if bc_MPS == 'finite' else 'periodic'
        lat = Chain(L, site, bc=bc, bc_MPS=bc_MPS)

        Sp, Sm, Sz = site.Sp, site.Sm, site.Sz
        S_dot_S = 0.5 * (kron(Sp, Sm) + kron(Sm, Sp)) + kron(Sz, Sz)
        S_dot_S_square = npc.tensordot(S_dot_S, S_dot_S, [['(p0*.p1*)'], ['(p0.p1)']])

        H_bond = S_dot_S + S_dot_S_square / 3.
        # P_2 = H_bond * 0.5 + 1/3 * npc.eye_like(S_dot_S)

        J = model_params.get('J', 1.)
        H_bond = J * H_bond.split_legs().transpose(['p0', 'p1', 'p0*', 'p1*'])
        H_bond = [H_bond] * L
        # H_bond[i] acts on sites (i-1, i)
        if bc_MPS == "finite":
            H_bond[0] = None
        # 7) initialize H_bond (the order of 7/8 doesn't matter)
        NearestNeighborModel.__init__(self, lat, H_bond)
        # 9) initialize H_MPO
        MPOModel.__init__(self, lat, self.calc_H_MPO_from_bond())
Пример #18
0
 def update_new_psi(self, theta):
     i0 = self.i0
     new_psi = self.psi
     qtotal_i0 = new_psi.get_B(i0, form=None).qtotal
     U, S, VH, err, renormalize = svd_theta(theta,
                                            self.trunc_params,
                                            qtotal_LR=[qtotal_i0, None],
                                            inner_labels=['vR', 'vL'])
     self.renormalize.append(renormalize)
     # TODO: up to the `renormalize`, we could use `new_psi.set_svd_theta`.
     A0 = U.split_legs(['(vL.p0.q0)'])
     B1 = VH.split_legs(['(p1.q1.vR)'])
     # first compare to old best guess to check convergence of the sweeps
     if self._tol_theta_diff is not None and self.update_LP_RP[0] == False:
         theta_old = new_psi.get_theta(i0)
         theta_new_trunc = npc.tensordot(A0.scale_axis(S, 'vR'), B1, ['vR', 'vL'])
         ov = npc.inner(theta_new_trunc, theta_old, do_conj=True, axes='labels')
         theta_diff = 1. - abs(ov)
         self._theta_diff.append(theta_diff)
     A0.ireplace_labels(['p0', 'q0'], ['p', 'q'])
     B1.ireplace_labels(['p1', 'q1'], ['p', 'q'])
     new_psi.set_B(i0, A0, form='A')  # left-canonical
     new_psi.set_B(i0 + 1, B1, form='B')  # right-canonical
     new_psi.set_SR(i0, S)
     return {'U': U, 'VH': VH, 'err': err}
Пример #19
0
def test_site():
    chinfo = npc.ChargeInfo([1, 3])
    leg = gen_random_legcharge(chinfo, 8)
    op1 = npc.Array.from_func(np.random.random, [leg, leg.conj()], shape_kw='size')
    op2 = npc.Array.from_func(np.random.random, [leg, leg.conj()], shape_kw='size')
    labels = ['up'] + [None] * (leg.ind_len - 2) + ['down']
    s = site.Site(leg, labels, silly_op=op1)
    assert s.state_index('up') == 0
    assert s.state_index('down') == leg.ind_len - 1
    assert s.opnames == set(['silly_op', 'Id', 'JW'])
    assert s.silly_op is op1
    s.add_op('op2', op2)
    assert s.op2 is op2
    assert s.get_op('op2') is op2
    assert s.get_op('silly_op') is op1
    npt.assert_equal(
        s.get_op('silly_op op2').to_ndarray(),
        npc.tensordot(op1, op2, [1, 0]).to_ndarray())
    leg2 = npc.LegCharge.from_drop_charge(leg, 1)
    leg2 = npc.LegCharge.from_change_charge(leg2, 0, 2, 'changed')
    s2 = copy.deepcopy(s)
    s2.change_charge(leg2)
    perm_qind, leg2s = leg2.sort()
    perm_flat = leg2.perm_flat_from_perm_qind(perm_qind)
    s2s = copy.deepcopy(s2)
    s2s.change_charge(leg2s, perm_flat)
    for site_check in [s2, s2s]:
        print("site_check.leg = ", site_check.leg)
        for opn in site_check.opnames:
            op1 = s.get_op(opn).to_ndarray()
            op2 = site_check.get_op(opn).to_ndarray()
            perm = site_check.perm
            npt.assert_equal(op1[np.ix_(perm, perm)], op2)
Пример #20
0
def test_npc_inner(tol=1.e-13):
    for sort in [True, False]:
        print("sort =", sort)
        a = random_Array((10, 7, 5), chinfo3, sort=sort)
        a.iset_leg_labels(['x', 'y', 'z'])
        aflat = a.to_ndarray()
        b = npc.Array.from_func(np.random.random, a.legs, qtotal=a.qtotal, shape_kw='size')
        b.iset_leg_labels(['x', 'y', 'z'])
        b_conj = b.conj()
        b_conj_flat = b.to_ndarray()
        cflat = np.tensordot(aflat, b_conj_flat, axes=[[0, 1, 2], [0, 1, 2]])
        c = npc.inner(a, b_conj, axes='range')  # no transpose
        assert type(c) == np.dtype(float)
        assert (abs(c - cflat) < tol)
        c = npc.inner(a, b_conj, axes=[[0, 1, 2], [0, 1, 2]])
        assert (abs(c - cflat) < tol)
        c = npc.inner(a, b, axes='range', do_conj=True)
        assert (abs(c - cflat) < tol)
        # now transpose
        b.itranspose([2, 1, 0])
        b_conj.itranspose([2, 1, 0])
        c = npc.inner(a, b_conj, axes=[[2, 0, 1], [0, 2, 1]])  # unordered axes!
        assert (abs(c - cflat) < tol)
        c = npc.inner(a, b_conj, axes='labels')
        assert (abs(c - cflat) < tol)
        c = npc.inner(a, b, axes='labels', do_conj=True)
        assert (abs(c - cflat) < tol)

    print("for trivial charge")
    a = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()], shape_kw='size')
    aflat = a.to_ndarray()
    b = npc.tensordot(a, a, axes=2)
    bflat = np.tensordot(aflat, aflat, axes=2)
    npt.assert_array_almost_equal_nulp(b, bflat, sum(a.shape))
Пример #21
0
def test_canonical_form(bc, method):
    psi = random_MPS(8, 2, 6, form=None, bc=bc)
    psi2 = psi.copy()
    norm = np.sqrt(psi2.overlap(psi2, ignore_form=True))
    print("norm =", norm)
    psi2.norm /= norm  # normalize psi2
    norm2 = psi.overlap(psi2, ignore_form=True)
    print("norm2 =", norm2)
    assert abs(norm2 - norm) < 1.e-14 * norm
    meth = getattr(psi, method)
    meth(renormalize=False)  # psi.canonical_form_[infinite[2]]()
    psi.test_sanity()
    assert abs(psi.norm - norm) < 1.e-14 * norm
    psi.norm = 1.  # normalized psi
    ov = psi.overlap(psi2, ignore_form=True)
    print("normalized states: overlap <psi_canonical|psi> = 1.-", 1. - ov)
    assert abs(ov - 1.) < 1.e-14
    print("norm_test")
    print(psi.norm_test())
    assert np.max(psi.norm_test()) < 1.e-14  # SB = AS to good precision
    psi3 = psi.copy()
    # call canonical_form again, it shouldn't do anything now
    meth(renormalize=True)
    psi.test_sanity()
    ov = psi.overlap(psi3)
    assert abs(ov - 1.) < 1.e-14
    if method in ['canonical_form_finite', 'canonical_form_infinite2']:
        # check that A = SB S^-1 is orthonormal
        for i in range(psi.L):
            A = psi.get_B(i, 'A')
            c = npc.tensordot(A, A.conj(), axes=[['vL', 'p'], ['vL*', 'p*']])
            A_err = (c - npc.diag(1., c.legs[0])).norm()
            print(A_err)
            assert A_err < 1.e-13
Пример #22
0
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!
Пример #23
0
def test_ExpMPOEvolution(bc_MPS, approximation, compression, g=1.5):
    # Test a time evolution against exact diagonalization for finite bc
    dt = 0.01
    if bc_MPS == 'finite':
        L = 6
    else:
        L = 2
    model_pars = dict(L=L,
                      Jx=0.,
                      Jy=0.,
                      Jz=-4.,
                      hx=2. * g,
                      bc_MPS=bc_MPS,
                      conserve=None)
    M = SpinChain(model_pars)
    state = ([[1 / np.sqrt(2), -1 / np.sqrt(2)]] * L
             )  # pointing in (-x)-direction
    state = ['up'] * L  # pointing in (-z)-direction
    psi = MPS.from_product_state(M.lat.mps_sites(), state, bc=bc_MPS)

    options = {
        'dt': dt,
        'N_steps': 1,
        'order': 1,
        'approximation': approximation,
        'compression_method': compression,
        'trunc_params': {
            'chi_max': 30
        }
    }
    eng = mpo_evolution.ExpMPOEvolution(psi, M, options)

    if bc_MPS == 'finite':
        ED = exact_diag.ExactDiag(M)
        ED.build_full_H_from_mpo()
        ED.full_diagonalization()
        psiED = ED.mps_to_full(psi)
        psiED /= psiED.norm()

        UED = ED.exp_H(dt)
        for i in range(30):
            psi = eng.run()
            psiED = npc.tensordot(UED, psiED, ('ps*', [0]))
            psi_full = ED.mps_to_full(psi)
            assert (abs(abs(npc.inner(psiED, psi_full, [0, 0], True)) - 1) <
                    dt)

    if bc_MPS == 'infinite':
        psiTEBD = psi.copy()
        TEBD_params = {'dt': dt, 'N_steps': 1}
        EngTEBD = tebd.Engine(psiTEBD, M, TEBD_params)
        for i in range(30):
            EngTEBD.run()
            psi = eng.run()
            print(psi.norm)
            print(np.abs(psi.overlap(psiTEBD) - 1))
            #This test fails
            assert (abs(abs(psi.overlap(psiTEBD)) - 1) < 1e-2)
Пример #24
0
    def sweep_right_left(self):
        """Performs the sweep right->left of the second order TDVP scheme with one site update. Evolve from 0.5*dt"""
        spectrum = []
        spectrum.append(np.array([1]))
        expectation_O = []
        for j in range(self.L - 1, -1, -1):
            B = self.psi.get_B(j, form='A')
            # Get theta
            if j == self.L - 1:
                theta = B
            else:
                theta = npc.tensordot(
                    s, B,
                    axes=('vL',
                          'vR'))  #theta[vL,p,vR]=s[vL,vR]*self.psi[p,vL,vR]
            theta = theta.transpose([
                'p',
                'vL',
                'vR',
            ])

            # Apply expm (-dt H) for 1-site
            chiB, chiA, d = theta.to_ndarray().shape
            Lp = self.environment.get_LP(j)
            Rp = self.environment.get_RP(j)
            W1 = self.environment.H.get_W(j)
            theta = self.update_theta_h1(Lp, Rp, theta, W1,
                                         -1j * 0.5 * self.dt)
            # SVD and update environment
            U, s, V = self.theta_svd_right_left(theta)
            spectrum.append(s / np.linalg.norm(s.to_ndarray()))
            self.psi.set_B(j, U, form='B')
            self._del_correct(j)
            if j > 0:
                # Apply expm (-dt H) for 0-site

                B = self.psi.get_B(j - 1, form='A')
                B_jm1 = npc.tensordot(V, B, axes=['vL', 'vR'])
                self.psi.set_B(j - 1, B_jm1, form='A')
                Lp = npc.tensordot(Lp, V, axes=['vR', 'vL'])
                Lp = npc.tensordot(Lp, V.conj(), axes=['vR*', 'vL*'])
                H = H0_mixed(Lp, self.environment.get_RP(j - 1))

                s = self.update_s_h0(s, H, 1j * 0.5 * self.dt)
                s = s / np.linalg.norm(s.to_ndarray())
Пример #25
0
def test_npc_svd():
    for m, n in [(1, 1), (1, 10), (10, 1), (10, 10), (10, 20)]:
        print("m, n = ", m, n)
        tol_NULP = max(20 * max(m, n)**3, 1000)
        for i in range(1000):
            A = random_Array((m, n), chinfo3, sort=True)
            if A.stored_blocks > 0:
                break
        Aflat = A.to_ndarray()
        Sonly = npc.svd(A, compute_uv=False)
        U, S, VH = npc.svd(A, full_matrices=False, compute_uv=True)
        assert (U.shape[1] == S.shape[0] == VH.shape[0])
        U.test_sanity()
        VH.test_sanity()
        npt.assert_array_almost_equal_nulp(Sonly, S, tol_NULP)
        recalc = npc.tensordot(U.scale_axis(S, axis=-1), VH, axes=1)
        npt.assert_array_almost_equal_nulp(recalc.to_ndarray(), Aflat,
                                           tol_NULP)
        # compare with flat SVD
        Uflat, Sflat, VHflat = np.linalg.svd(Aflat, False, True)
        perm = np.argsort(-S)  # sort descending
        print(S[perm])
        iperm = inverse_permutation(perm)
        for i in range(len(Sflat)):
            if i not in iperm:  # dopped it in npc.svd()
                assert (Sflat[i] < EPS * 10)
        Sflat = Sflat[iperm]
        npt.assert_array_almost_equal_nulp(Sonly, Sflat, tol_NULP)
        # comparing U and Uflat is hard: U columns can change by a phase...
    print("with full_matrices")
    Ufull, Sfull, VHfull = npc.svd(A, full_matrices=True, compute_uv=True)
    Ufull.test_sanity()
    VHfull.test_sanity()
    npt.assert_array_almost_equal_nulp(Sfull, S, tol_NULP)

    print("for trivial charges")
    A = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()],
                            shape_kw='size')
    Aflat = A.to_ndarray()
    U, S, VH = npc.svd(A)
    recalc = npc.tensordot(U.scale_axis(S, axis=-1), VH, axes=1)
    tol_NULP = max(20 * max(A.shape)**3, 1000)
    npt.assert_array_almost_equal_nulp(recalc.to_ndarray(), Aflat, tol_NULP)
Пример #26
0
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.")
Пример #27
0
def test_npc_outer():
    for sort in [True, False]:
        print("sort =", sort)
        a = random_Array((6, 7), chinfo3, sort=sort)
        b = random_Array((5, 5), chinfo3, sort=sort)
        aflat = a.to_ndarray()
        bflat = b.to_ndarray()
        c = npc.outer(a, b)
        c.test_sanity()
        cflat = np.tensordot(aflat, bflat, axes=0)
        npt.assert_equal(c.to_ndarray(), cflat)
        c = npc.tensordot(a, b, axes=0)  # (should as well call npc.outer)
        npt.assert_equal(c.to_ndarray(), cflat)

    print("for trivial charge")
    a = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()], shape_kw='size')
    aflat = a.to_ndarray()
    b = npc.tensordot(a, a, axes=0)
    bflat = np.tensordot(aflat, aflat, axes=0)
    npt.assert_array_almost_equal_nulp(b.to_ndarray(), bflat, sum(a.shape))
Пример #28
0
def test_qr():
    for shape in [(4, 4), (6, 8), (8, 6)]:
        for qtotal in [None, [1]]:
            print("qtotal=", qtotal, "shape =", shape)
            A = random_Array(shape, chinfo3, qtotal=qtotal, sort=False)
            A_flat = A.to_ndarray()
            q, r = npc.qr(A, 'reduced')
            print(q._qdata)
            q.test_sanity()
            r.test_sanity()
            qr = npc.tensordot(q, r, axes=1)
            npt.assert_array_almost_equal_nulp(A_flat, qr.to_ndarray(), shape[0] * shape[1] * 100)
Пример #29
0
def check_hermitian(H):
    """Check if `H` is a hermitian MPO."""
    if not H.finite:
        # include once over the boundary: double the unit cell
        # a general MPO might have terms going over multiple unit cells, but we ignore that...
        Ws = H._W * 2
    else:
        Ws = H._W
    #check trace(H.H) = trace(H.H^dagger):  equivalent to H=H^dagger
    W = Ws[0].take_slice([H.get_IdL(0)], ['wL'])

    trHH = npc.tensordot(W,
                         W.replace_label('wR', 'wR*'),
                         axes=[['p', 'p*'], ['p*', 'p']])
    trHHd = npc.tensordot(W, W.conj(), axes=[['p', 'p*'], ['p*', 'p']])
    for W in Ws[1:]:
        trHH = npc.tensordot(trHH, W, axes=['wR', 'wL'])
        trHHd = npc.tensordot(trHHd, W, axes=['wR', 'wL'])
        trHH = npc.tensordot(trHH,
                             W.replace_label('wR', 'wR*'),
                             axes=[['wR*', 'p', 'p*'], ['wL', 'p*', 'p']])
        trHHd = npc.tensordot(trHHd,
                              W.conj(),
                              axes=[['wR*', 'p', 'p*'], ['wL*', 'p*', 'p']])
    i = H.get_IdR(H.L - 1)
    trHH = trHH[i, i]
    trHHd = trHHd[i, i]
    print("check_hermitian: ", trHH, trHHd)
    npt.assert_array_almost_equal_nulp(trHH, trHHd, H.L * 20)
Пример #30
0
    def sweep_left_right(self):
        """Performs the sweep left->right of the second order TDVP scheme with one site update.

        Evolve from 0.5*dt.
        """
        for j in range(self.L):
            B = self.psi.get_B(j)
            # Get theta
            if j == 0:
                theta = B
            else:
                theta = npc.tensordot(
                    B, s,
                    axes=('vL',
                          'vR'))  #theta[vL,p,vR]=s[vL,vR]*self.psi[p,vL,vR]
            Lp = self.environment.get_LP(j)
            Rp = self.environment.get_RP(j)
            W1 = self.environment.H.get_W(j)
            theta = self.update_theta_h1(Lp, Rp, theta, W1,
                                         -1j * 0.5 * self.dt)
            # SVD and update environment
            U, s, V = self.theta_svd_left_right(theta)
            self.psi.set_B(j, U, form='A')
            self.psi.set_SR(j, np.diag(s.to_ndarray()))
            self._del_correct(j)
            if j < self.L - 1:
                # Apply expm (-dt H) for 0-site

                B = self.psi.get_B(j + 1)
                B_jp1 = npc.tensordot(V, B, axes=['vR', 'vL'])
                self.psi.set_B(j + 1, B_jp1, form='B')
                Lpp = self.environment.get_LP(j + 1)
                Rp = npc.tensordot(Rp, V, axes=['vL', 'vR'])
                Rp = npc.tensordot(Rp, V.conj(), axes=['vL*', 'vR*'])
                H = H0_mixed(Lpp, Rp)

                s = self.update_s_h0(s, H, 1j * 0.5 * self.dt)
                s = s / np.linalg.norm(s.to_ndarray())