Example #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')
Example #2
0
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
Example #3
0
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
Example #4
0
def heisenberg_XXZ_comm_MPO(L, J, D, h):
    """Construct commutator with XXZ Heisenberg Hamiltonian
    'sum J X X + J Y Y + D Z Z - h Z' on a 1D lattice as MPO."""
    # physical quantum numbers (multiplied by 2)
    qd = np.array([1, -1])
    # spin operators
    Sup = np.array([[0., 1.], [0., 0.]])
    Sdn = np.array([[0., 0.], [1., 0.]])
    Sz = np.array([[0.5, 0.], [0., -0.5]])
    # local two-site and single-site terms
    lopchains = [
        ptn.OpChain([0.5 * J * Sup, Sdn], [2]),
        ptn.OpChain([0.5 * J * Sdn, Sup], [-2]),
        ptn.OpChain([D * Sz, Sz], [0]),
        ptn.OpChain([-h * Sz], [])
    ]
    # convert to MPO form, with local terms acting either on first or second physical dimension
    locopchains = []
    for opchain in lopchains:
        locopchains += construct_comm_opchain(opchain)
    return ptn.local_opchains_to_MPO(ptn.qnumber_flatten([qd, -qd]), L,
                                     locopchains)