Esempio n. 1
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)
Esempio n. 2
0
 def calc_B(self, M):
     """Performs the SVD to extract B from s * theta
     Parameters
     ----------
     M: :class:`tenpy.linalg.np_conserved.Array`
         the tensor to apply svd to
     """
     M = M.combine_legs(['p', 'vR'])
     U, s, V = npc.svd(M, full_matrices=0)
     V = V.split_legs(['(p.vR)'])
     V = self.set_anonymous_svd(V, 'vL')  #V['vL','p','vR']
     U = self.set_anonymous_svd(U, 'vR')  #U['vL','vR']
     new_B = npc.tensordot(U, V, axes=('vR', 'vL'))
     return new_B
Esempio n. 3
0
 def calc_A(self, M):
     """Performs the SVD to extract A from theta * s
     Parameters
     ----------
     M: :class:`tenpy.linalg.np_conserved.Array`
         the tensor to apply svd to
     """
     M = M.combine_legs(['vL', 'p'])
     U, s, V = npc.svd(M, full_matrices=0)
     U = U.split_legs(['(vL.p)'])
     U = self.set_anonymous_svd(U, 'vR')  #U['vL','p','vR']
     V = self.set_anonymous_svd(V, 'vL')  #V['vL','vR']
     new_A = npc.tensordot(U, V, axes=('vR', 'vL'))  #A['vL','p','vR']
     return new_A
Esempio n. 4
0
    def gauge_transform(self, A, B, theta, C):

        U, s, Vdag = npc.svd(C, full_matrices=0)
        U = self.set_anonymous_svd(U, 'vR')
        Vdag = self.set_anonymous_svd(Vdag, 'vL')
        Udag = U.conj().itranspose(['vR*',
                                    'vL*']).iset_leg_labels(['vL', 'vR'])
        V = Vdag.conj().itranspose(['vR*',
                                    'vL*']).iset_leg_labels(['vL', 'vR'])

        Ap = npc.tensordot(Udag, A, axes=('vR', 'vL'))
        Ap = npc.tensordot(Ap, U, axes=('vR', 'vL'))
        Bp = npc.tensordot(Vdag, B, axes=('vR', 'vL'))
        Bp = npc.tensordot(Bp, V, axes=('vR', 'vL'))
        thetap = npc.tensordot(Udag, theta, axes=('vR', 'vL'))
        thetap = npc.tensordot(thetap, V, axes=('vR', 'vL'))
        return Ap, Bp, thetap, s
Esempio n. 5
0
    def update_AB(self, A, B, theta, C):
        U, s, V = npc.svd(C, full_matrices=0)
        U = self.set_anonymous_svd(U, 'vR')
        V = self.set_anonymous_svd(V, 'vL')

        Udag = U.conj()
        Vdag = V.conj()

        new_A = npc.tensordot(Udag, A, axes=('vL*', 'vL'))
        new_A = npc.tensordot(new_A, U, axes=('vR', 'vL'))
        new_B = npc.tensordot(V, B, axes=('vR', 'vL'))
        new_B = npc.tensordot(new_B, Vdag, axes=('vR', 'vR*'))
        new_theta = npc.tensordot(Udag, theta, axes=('vL*', 'vL'))
        new_theta = npc.tensordot(new_theta, Vdag, axes=('vR', 'vR*'))
        new_A.iset_leg_labels(['vL', 'p', 'vR'])
        new_B.iset_leg_labels(['vL', 'p', 'vR'])
        new_theta.iset_leg_labels(['vL', 'p', 'vR'])
        return new_A, new_B, new_theta, s
Esempio n. 6
0
 def theta_svd_right_left(self, theta):
     """Performs the SVD from right to left"""
     theta = theta.transpose(['vL', 'p', 'vR'])
     theta = theta.combine_legs(['p', 'vR'])
     theta = theta.transpose(['vL', '(p.vR)'])
     V, s, U = npc.svd(theta, full_matrices=0)
     U = U.split_legs(['(p.vR)'])
     U = self.set_anonymous_svd(U, 'vL')
     V = self.set_anonymous_svd(V, 'vR')
     s_ndarray = np.diag(s)
     vL_U = U.get_leg('vL')
     vR_V = V.get_leg('vR')
     s = npc.Array.from_ndarray(s_ndarray,
                                [vR_V.conj(), vL_U.conj()],
                                dtype=None,
                                qtotal=None,
                                cutoff=None)
     s.iset_leg_labels(['vL', 'vR'])
     return U, s, V
Esempio n. 7
0
    def theta_svd_right_left(self, theta):
        """Performs the SVD from right to left

        Parameters
        ----------
        theta : :class:`tenpy.linalg.np_conserved.Array`,
            The theta tensor on which the SVD is applied
        """
        theta = theta.combine_legs(['p', 'vR'])
        V, s, U = npc.svd(theta, full_matrices=0)
        U = U.split_legs(['(p.vR)'])
        U = self.set_anonymous_svd(U, 'vL')
        V = self.set_anonymous_svd(V, 'vR')
        s_ndarray = np.diag(s)
        vL_U = U.get_leg('vL')
        vR_V = V.get_leg('vR')
        s = npc.Array.from_ndarray(s_ndarray, [vR_V.conj(), vL_U.conj()],
                                   dtype=None,
                                   qtotal=None,
                                   cutoff=None)
        s.iset_leg_labels(['vL', 'vR'])
        return U, s, V
Esempio n. 8
0
exp_H2 = exp_H2.split_legs()  # by default split all legs which are `LegPipe`
# (this restores the originial labels ['p0', 'p1', 'p0*', 'p1*'] of `H2` in `exp_H2`)

print("7) apply exp(H2) to even/odd bonds of the MPS and truncate with svd")
# (this implements one time step of first order TEBD)
for even_odd in [0, 1]:
    for i in range(even_odd, L - 1, 2):
        B_L = Bs[i].scale_axis(Ss[i], 'vL').ireplace_label('p', 'p0')
        B_R = Bs[i + 1].replace_label('p', 'p1')
        theta = npc.tensordot(B_L, B_R, axes=('vR', 'vL'))
        theta = npc.tensordot(exp_H2,
                              theta,
                              axes=(['p0*', 'p1*'], ['p0', 'p1']))
        # view as matrix for SVD
        theta = theta.combine_legs([('vL', 'p0'), ('p1', 'vR')],
                                   new_axes=[0, 1],
                                   qconj=[+1, -1])
        # now theta has labels '(vL.p0)', '(p1.vR)'
        U, S, V = npc.svd(theta, inner_labels=['vR', 'vL'])
        # truncate
        keep = S > cutoff
        S = S[keep]
        invsq = np.linalg.norm(S)
        Ss[i + 1] = S / invsq
        U = U.iscale_axis(S / invsq, 'vR')
        Bs[i] = U.split_legs('(vL.p0)').iscale_axis(Ss[i]**(-1),
                                                    'vL').ireplace_label(
                                                        'p0', 'p')
        Bs[i + 1] = V.split_legs('(p1.vR)').ireplace_label('p1', 'p')
print("finished")