コード例 #1
0
    def test_split_tensor(self):

        # physical dimensions
        d0, d1 = 3, 5
        # outer virtual bond dimensions
        D0, D2 = 14, 17

        Apair = randn_complex((d0*d1, D0, D2)) / np.sqrt(d0*d1*D0*D2)

        # fictitious quantum numbers
        qd0 = np.random.randint(-2, 3, size=d0)
        qd1 = np.random.randint(-2, 3, size=d1)
        qD = [np.random.randint(-2, 3, size=D0), np.random.randint(-2, 3, size=D2)]

        # enforce block sparsity structure dictated by quantum numbers
        mask = ptn.qnumber_outer_sum([ptn.qnumber_flatten([qd0, qd1]), qD[0], -qD[1]])
        Apair = np.where(mask == 0, Apair, 0)

        for svd_distr in ['left', 'right', 'sqrt']:
            (A0, A1, qbond) = ptn.split_MPS_tensor(Apair, qd0, qd1, qD, svd_distr=svd_distr, tol=0)

            self.assertTrue(ptn.is_qsparse(A0, [qd0, qD[0], -qbond]),
                            msg='sparsity pattern of A0 tensors must match quantum numbers')
            self.assertTrue(ptn.is_qsparse(A1, [qd1, qbond, -qD[1]]),
                            msg='sparsity pattern of A1 tensors must match quantum numbers')

            # merged tensor must agree with the original tensor
            Amrg = ptn.merge_MPS_tensor_pair(A0, A1)
            self.assertAlmostEqual(np.linalg.norm(Amrg - Apair), 0., delta=1e-13,
                                   msg='splitting and subsequent merging must give the same tensor')
コード例 #2
0
ファイル: test_bond_ops.py プロジェクト: ml-lab/pytenet
    def test_qr(self):

        A = randn_complex((23, 15))

        # fictitious quantum numbers
        q0 = np.random.randint(-2, 3, size=A.shape[0])
        q1 = np.random.randint(-2, 3, size=A.shape[1])

        # enforce block sparsity structure dictated by quantum numbers
        mask = ptn.qnumber_outer_sum([q0, -q1])
        A = np.where(mask == 0, A, 0)

        # perform QR decomposition, taking quantum numbers into account
        Q, R, qinterm = ptn.qr(A, q0, q1)

        self.assertAlmostEqual(np.linalg.norm(np.dot(Q, R) - A),
                               0.,
                               delta=1e-14,
                               msg='Q.R must match A matrix')

        self.assertAlmostEqual(
            np.linalg.norm(np.dot(Q.conj().T, Q) - np.identity(Q.shape[1])),
            0.,
            delta=1e-14,
            msg='columns of Q matrix must be orthonormalized')

        self.assertTrue(
            ptn.is_qsparse(Q, [q0, -qinterm]),
            msg='sparsity pattern of Q matrix must match quantum numbers')
        self.assertTrue(
            ptn.is_qsparse(R, [qinterm, -q1]),
            msg='sparsity pattern of R matrix must match quantum numbers')
コード例 #3
0
ファイル: test_bond_ops.py プロジェクト: ml-lab/pytenet
    def test_split_matrix_svd(self):

        A = randn_complex((17, 26))

        # fictitious quantum numbers
        q0 = np.random.randint(-2, 3, size=A.shape[0])
        q1 = np.random.randint(-2, 3, size=A.shape[1])

        # enforce block sparsity structure dictated by quantum numbers
        mask = ptn.qnumber_outer_sum([q0, -q1])
        A = np.where(mask == 0, A, 0)

        # perform SVD decomposition without truncation
        u, s, v, qinterm = ptn.split_matrix_svd(A, q0, q1, 0.)

        self.assertAlmostEqual(np.linalg.norm(np.dot(u * s, v) - A),
                               0.,
                               delta=1e-13,
                               msg='U.S.V must match A matrix')

        self.assertAlmostEqual(
            np.linalg.norm(np.dot(u.conj().T, u) - np.identity(u.shape[1])),
            0.,
            delta=1e-14,
            msg='columns of U matrix must be orthonormalized')

        self.assertTrue(
            ptn.is_qsparse(u, [q0, -qinterm]),
            msg='sparsity pattern of U matrix must match quantum numbers')
        self.assertTrue(
            ptn.is_qsparse(v, [qinterm, -q1]),
            msg='sparsity pattern of V matrix must match quantum numbers')

        s_norm = np.linalg.norm(s)

        # perform SVD decomposition with truncation
        u, s, v, qinterm = ptn.split_matrix_svd(A, q0, q1, 0.15)

        self.assertAlmostEqual(
            np.linalg.norm(np.dot(u * s, v) - A),
            np.sqrt(s_norm**2 - np.linalg.norm(s)**2),
            delta=1e-14,
            msg=
            'weight of truncated singular values must agree with norm of matrix difference'
        )

        self.assertAlmostEqual(
            np.linalg.norm(np.dot(u.conj().T, u) - np.identity(u.shape[1])),
            0.,
            delta=1e-14,
            msg='columns of U matrix must be orthonormalized')

        self.assertTrue(
            ptn.is_qsparse(u, [q0, -qinterm]),
            msg='sparsity pattern of U matrix must match quantum numbers')
        self.assertTrue(
            ptn.is_qsparse(v, [qinterm, -q1]),
            msg='sparsity pattern of V matrix must match quantum numbers')
コード例 #4
0
ファイル: evolution_operator.py プロジェクト: ml-lab/pytenet
def cast_to_MPS(mpo):
    """
    Cast a matrix product operator into MPS form by combining the pair of local
    physical dimensions into one dimension.
    """
    mps = ptn.MPS(ptn.qnumber_flatten([mpo.qd, -mpo.qd]), mpo.qD, fill=0.0)
    for i in range(mpo.nsites):
        s = mpo.A[i].shape
        mps.A[i] = mpo.A[i].reshape((s[0] * s[1], s[2], s[3])).copy()
        assert ptn.is_qsparse(mps.A[i], [mps.qd, mps.qD[i], -mps.qD[i + 1]])
    return mps
コード例 #5
0
ファイル: evolution_operator.py プロジェクト: ml-lab/pytenet
def cast_to_MPO(mps, qd):
    """
    Cast a matrix product state into MPO form by interpreting the physical
    dimension as Kronecker product of a pair of dimensions.
    """
    assert np.array_equal(mps.qd, ptn.qnumber_flatten([qd, -qd]))

    mpo = ptn.MPO(qd, mps.qD, fill=0.0)
    for i in range(mps.nsites):
        s = mps.A[i].shape
        mpo.A[i] = mps.A[i].reshape((len(qd), len(qd), s[1], s[2])).copy()
        assert ptn.is_qsparse(mpo.A[i],
                              [mpo.qd, -mpo.qd, mpo.qD[i], -mpo.qD[i + 1]])
    return mpo
コード例 #6
0
    def test_from_opchains(self):

        # dimensions
        d = 4
        L = 5

        # physical quantum numbers
        qd = np.random.randint(-2, 3, size=d)

        # fictitious operator chains
        opchains = []
        n = np.random.randint(20)
        for _ in range(n):
            istart = np.random.randint(L)
            length = np.random.randint(1, L - istart + 1)
            oplist = [randn_complex((d, d)) for _ in range(length)]
            qD = np.random.randint(-2, 3, size=length - 1)
            # enforce sparsity structure dictated by quantum numbers
            qDpad = np.pad(qD, 1, mode='constant')
            for i in range(length):
                mask = ptn.qnumber_outer_sum(
                    [qd + qDpad[i], -(qd + qDpad[i + 1])])
                oplist[i] = np.where(mask == 0, oplist[i], 0)
            opchains.append(ptn.OpChain(oplist, qD, istart))

        # construct MPO representation corresponding to operator chains
        mpo0 = ptn.MPO.from_opchains(qd, L, opchains)

        for i in range(mpo0.nsites):
            self.assertTrue(
                ptn.is_qsparse(
                    mpo0.A[i],
                    [mpo0.qd, -mpo0.qd, mpo0.qD[i], -mpo0.qD[i + 1]]),
                msg='sparsity pattern of MPO tensors must match quantum numbers'
            )

        # construct full Hamiltonian from operator chains, as reference
        Href = sum([opc.as_matrix(d, L) for opc in opchains])

        # compare
        self.assertAlmostEqual(
            np.linalg.norm(mpo0.as_matrix() - Href),
            0.,
            delta=1e-10,
            msg=
            'full merging of MPO must be equal to matrix representation of operator chains'
        )
コード例 #7
0
    def test_orthonormalization(self):

        # create random matrix product state
        d = 7
        D = [1, 4, 15, 13, 7, 1]
        mps0 = ptn.MPS(np.random.randint(-2, 3, size=d), [np.random.randint(-2, 3, size=Di) for Di in D], fill='random')

        self.assertEqual(mps0.bond_dims, D, msg='virtual bond dimensions')

        # wavefunction on full Hilbert space
        psi = mps0.as_vector()

        # performing left-orthonormalization...
        cL = mps0.orthonormalize(mode='left')

        self.assertLessEqual(mps0.bond_dims[1], d,
            msg='virtual bond dimension can only increase by a factor of "d" per site')

        for i in range(mps0.nsites):
            self.assertTrue(ptn.is_qsparse(mps0.A[i], [mps0.qd, mps0.qD[i], -mps0.qD[i+1]]),
                            msg='sparsity pattern of MPS tensors must match quantum numbers')

        psiL = mps0.as_vector()
        # wavefunction should now be normalized
        self.assertAlmostEqual(np.linalg.norm(psiL), 1., delta=1e-12, msg='wavefunction normalization')

        # wavefunctions before and after left-normalization must match
        # (up to normalization factor)
        self.assertAlmostEqual(np.linalg.norm(cL*psiL - psi), 0., delta=1e-10,
                               msg='wavefunctions before and after left-normalization must match')

        # check left-orthonormalization
        for i in range(mps0.nsites):
            s = mps0.A[i].shape
            assert s[0] == d
            Q = mps0.A[i].reshape((s[0]*s[1], s[2]))
            QH_Q = np.dot(Q.conj().T, Q)
            self.assertAlmostEqual(np.linalg.norm(QH_Q - np.identity(s[2])), 0., delta=1e-12,
                                   msg='left-orthonormalization')

        # performing right-orthonormalization...
        cR = mps0.orthonormalize(mode='right')

        self.assertLessEqual(mps0.bond_dims[-2], d,
            msg='virtual bond dimension can only increase by a factor of "d" per site')

        for i in range(mps0.nsites):
            self.assertTrue(ptn.is_qsparse(mps0.A[i], [mps0.qd, mps0.qD[i], -mps0.qD[i+1]]),
                            msg='sparsity pattern of MPS tensors must match quantum numbers')

        self.assertAlmostEqual(abs(cR), 1., delta=1e-12,
            msg='normalization factor must have magnitude 1 due to previous left-orthonormalization')

        psiR = mps0.as_vector()
        # wavefunctions must match
        self.assertAlmostEqual(np.linalg.norm(psiL - cR*psiR), 0., delta=1e-10,
                               msg='wavefunctions after left- and right-orthonormalization must match')

        # check right-orthonormalization
        for i in range(mps0.nsites):
            s = mps0.A[i].shape
            assert s[0] == d
            Q = mps0.A[i].transpose((0, 2, 1)).reshape((s[0]*s[2], s[1]))
            QH_Q = np.dot(Q.conj().T, Q)
            self.assertAlmostEqual(np.linalg.norm(QH_Q - np.identity(s[1])), 0., delta=1e-12,
                                   msg='right-orthonormalization')
コード例 #8
0
    def test_orthonormalization(self):

        # create random matrix product operator
        d = 4
        D = [1, 10, 13, 14, 7, 1]
        mpo0 = ptn.MPO(np.random.randint(-2, 3, size=d),
                       [np.random.randint(-2, 3, size=Di) for Di in D],
                       fill='random')

        self.assertEqual(mpo0.bond_dims, D, msg='virtual bond dimensions')

        # density matrix on full Hilbert space
        rho = mpo0.as_matrix()

        # performing left-orthonormalization...
        cL = mpo0.orthonormalize(mode='left')

        self.assertLessEqual(
            mpo0.bond_dims[1],
            d**2,
            msg=
            'virtual bond dimension can only increase by factor of "d^2" per site'
        )

        for i in range(mpo0.nsites):
            self.assertTrue(
                ptn.is_qsparse(
                    mpo0.A[i],
                    [mpo0.qd, -mpo0.qd, mpo0.qD[i], -mpo0.qD[i + 1]]),
                msg='sparsity pattern of MPO tensors must match quantum numbers'
            )

        rhoL = mpo0.as_matrix()
        # density matrix should now be normalized
        self.assertAlmostEqual(np.linalg.norm(rhoL, 'fro'),
                               1.,
                               delta=1e-12,
                               msg='density matrix normalization')

        # density matrices before and after left-normalization must match
        # (up to normalization factor)
        self.assertAlmostEqual(
            np.linalg.norm(cL * rhoL - rho),
            0.,
            delta=1e-10,
            msg=
            'density matrices before and after left-normalization must match')

        # check left-orthonormalization
        for i in range(mpo0.nsites):
            s = mpo0.A[i].shape
            assert s[0] == d and s[1] == d
            Q = mpo0.A[i].reshape((s[0] * s[1] * s[2], s[3]))
            QH_Q = np.dot(Q.conj().T, Q)
            self.assertAlmostEqual(np.linalg.norm(QH_Q - np.identity(s[3])),
                                   0.,
                                   delta=1e-12,
                                   msg='left-orthonormalization')

        # performing right-orthonormalization...
        cR = mpo0.orthonormalize(mode='right')

        self.assertLessEqual(
            mpo0.bond_dims[-2],
            d**2,
            msg=
            'virtual bond dimension can only increase by factor of "d^2" per site'
        )

        for i in range(mpo0.nsites):
            self.assertTrue(
                ptn.is_qsparse(
                    mpo0.A[i],
                    [mpo0.qd, -mpo0.qd, mpo0.qD[i], -mpo0.qD[i + 1]]),
                msg='sparsity pattern of MPO tensors must match quantum numbers'
            )

        self.assertAlmostEqual(
            abs(cR),
            1.,
            delta=1e-12,
            msg=
            'normalization factor must have magnitude 1 due to previous left-orthonormalization'
        )

        rhoR = mpo0.as_matrix()
        # density matrices must match
        self.assertAlmostEqual(
            np.linalg.norm(rhoL - cR * rhoR),
            0.,
            delta=1e-10,
            msg=
            'density matrices after left- and right-orthonormalization must match'
        )

        # check right-orthonormalization
        for i in range(mpo0.nsites):
            s = mpo0.A[i].shape
            assert s[0] == d and s[1] == d
            Q = mpo0.A[i].transpose((0, 1, 3, 2)).reshape(
                (s[0] * s[1] * s[3], s[2]))
            QH_Q = np.dot(Q.conj().T, Q)
            self.assertAlmostEqual(np.linalg.norm(QH_Q - np.identity(s[2])),
                                   0.,
                                   delta=1e-12,
                                   msg='right-orthonormalization')