Пример #1
0
    def update(b, env):
        c, t = env

        # C insertion
        c_tilde = ncon([c, t, t, b, np.conj(b)],
                       [[1, 2], [2, 3, 4, -4], [-1, 5, 6, 1],
                        [7, 3, 5, -2, -5], [7, 4, 6, -3, -6]],
                       [1, 2, 3, 5, 4, 6, 7])
        # (D,d,d',R,r,r') -> (D~,R~)
        _D, _d, _d_, _R, _r, _r_ = c_tilde.shape
        c_tilde = np.reshape(c_tilde, [_D * _d * _d_, _R * _r * _r_])
        # T insertion
        t_tilde = ncon(
            [t, b, np.conj(b)],
            [[-1, 1, 2, -6], [3, 1, -2, -4, -7], [3, 2, -3, -5, -8]])
        # (L,l,l',d,d',R,r,r') -> (L~,d,d',R~)
        _L, _l, _l_, _d, _d_, _R, _r, _r_ = t_tilde.shape
        t_tilde = np.reshape(t_tilde, [_L * _l * _l_, _d, _d_, _R * _r * _r_])

        # enforce symmetry
        c_tilde = _c4v_symmetrise_c(c_tilde)

        # find projector
        P, _, _ = svd_truncated(c_tilde, chi_max=chi_ctm, cutoff=0.)  # (D~,R)

        # renormalise
        c = np.transpose(P) @ c_tilde @ P
        t = ncon([np.conj(P), t_tilde, np.conj(P)],
                 [[1, -1], [1, -2, -3, 2], [2, -4]])

        # enforce symmetry
        env = _c4v_symmetrise(c, t)

        return env
Пример #2
0
def _variance(c: np.ndarray, t: np.ndarray) -> float:
    """
    Returns the variance |<aa aa>| - <aa>**2 that would be zero for the fixed point of the RG
    This version is only checking if c and t are ANY environment, see also `_variance3`

    Parameters
    ----------
    c
        The corner matrix c(d, r) with `chi`-dimensional legs
    t
        The half-column / half-row tensor t(l, d, d', r)
    Returns
    -------
    var : float
        The variance

    """

    #          c --- c               c --- t --- c                     c --- t --- t --- c
    #  lr  =   |     |      ltr  =   |     |     |         lttr   =    |     |     |     |
    #          c --- c               c --- t --- c                     c --- t --- t --- c
    # if RG fixed point is reached then lttr/lr = <tt> = <t>**2 = (ltr/lr)**2

    lr = np.trace(c @ c @ c @ c)

    connects = [[1, 6], [6, 7, 8, 5], [5, 4], [4, 3], [2, 1], [2, 7, 8, 3]]
    cont_order = [
        4,
        1,
        3,
        2,
        6,
        5,
        7,
        8,
    ]
    ltr = ncon([c, t, c, c, c, t], connects, cont_order)

    connects = [[1, 4], [4, 5, 6, 9], [10, 3], [3, 11], [2, 1], [2, 5, 6, 12],
                [9, 7, 8, 10], [12, 7, 8, 11]]
    cont_order = [
        1,
        2,
        3,
        11,
        10,
        7,
        8,
        12,
        4,
        5,
        6,
        9,
    ]
    lttr = ncon([c, t, c, c, c, t, t, t], connects, cont_order)

    return abs(lttr / lr) - (ltr / lr)**2
Пример #3
0
def contract_closed_network(tensors,
                            connects,
                            contraction_order=None,
                            check_network=True):
    if not all([all([con > 0 for con in tens_cons])
                for tens_cons in connects]):
        raise ValueError('Not a closed network')

    return ncon(tensors, connects, contraction_order, check_network)
Пример #4
0
def two_layers(bra_tensors, ket_tensors):
    lx, ly = len(bra_tensors), len(bra_tensors[0])
    assert all(len(bra_tensors[x]) == ly for x in range(lx))
    assert len(ket_tensors) == lx
    assert all(len(ket_tensors[x]) == ly for x in range(lx))

    tensors = [ket_tensors[x][y] for y in range(ly) for x in range(lx)] \
              + [bra_tensors[x][y] for y in range(ly) for x in range(lx)]

    connects, order = _get_instructions2(lx, ly)
    return ncon(tensors, connects, order)
Пример #5
0
def _build_evolution_pepo(u_vert,
                          A,
                          bc: str,
                          lx: Optional[int] = None,
                          ly: Optional[int] = None) -> Operator:
    # DOC : lx, ly have no effect for INFINITE

    u_bulk = ncon(
        [u_vert, A, A, A, A, u_vert],
        [[1, -2], [2, 1, -6], [3, 2, -3], [4, 3, -4], [5, 4, -5], [-1, 5]])

    if bc == PBC:
        if (lx is None) or (ly is None):
            raise ValueError
        tensors = [[u_bulk for _ in range(ly)] for _ in range(lx)]
        return Pepo(tensors, bc=PBC, hermitian=False)

    elif bc == OBC:
        if (lx is None) or (ly is None):
            raise ValueError

        u_edge = ncon([u_vert, A, A, A, u_vert],
                      [[1, -2], [2, 1, -5], [3, 2, -3], [4, 3, -4], [-1, 4]])
        u_corner = ncon([u_vert, A, A, u_vert],
                        [[1, -2], [2, 1, -3], [3, 2, -4], [-1, 3]])

        tensors = [[u_corner] + [u_edge for _ in range(ly - 2)] + [u_corner]] \
                  + [[u_edge] + [u_bulk for _ in range(ly - 2)] + [u_edge] for _ in range(lx - 2)] \
                  + [[u_corner] + [u_edge for _ in range(ly - 2)] + [u_corner]]
        return Pepo(tensors, bc=OBC, hermitian=False)

    elif bc == INFINITE:
        return Ipepo([u_bulk],
                     unit_cell=np.array([[0]]),
                     symmetry='c4v',
                     hermitian=False)

    raise ValueError(f'Unknown boundary conditions: {bc}')
Пример #6
0
def _get_env(tensors, connects, contraction_order, check_network, n):
    assert 0 <= n < len(tensors)
    # remove tensors[n]
    tensors = tensors[:n] + tensors[n + 1:]

    # adjust connects. deep copy to avoid list-mutation problems
    connects = [sublist[:] for sublist in connects]
    # replace labels of legs that would be contracted with tensors[n] by open labels
    cons_to_be_removed = connects.pop(n)
    for n, con in enumerate(cons_to_be_removed):
        connects = [[-(n + 1) if c == con else c for c in sublist]
                    for sublist in connects]

    # remove labels from order
    if contraction_order:
        contraction_order = [
            i for i in contraction_order if (i not in cons_to_be_removed)
        ]

    env = ncon(tensors, connects, contraction_order, check_network)

    return env
Пример #7
0
def expval(env_tensors, ipeps_tensors, operator, operator_geometry):
    ipeps_tensor, = ipeps_tensors
    c, t = env_tensors
    chi_ctm = c.shape[0]
    chi_peps = ipeps_tensor.shape[1]
    d = operator.shape[0]

    n_sites = len(operator.shape) // 2
    assert c.shape == (chi_ctm, chi_ctm)
    assert t.shape == (chi_ctm, chi_peps, chi_peps, chi_ctm)
    assert ipeps_tensor.shape == (d, ) + 4 * (chi_peps, )
    assert operator.shape == (d, ) * (2 * n_sites)
    assert np.all(operator_geometry < n_sites)

    if operator_geometry.shape == (1, 1):  # single-site operator
        #                                            /
        #     c - t - c                           - a -
        #     |   |   |                 |         / |
        #     t - B - t               - B -   =     OP
        #     |   |   |                 |           | /
        #     c - t - c                           - a -
        #                                          /

        tensors = [
            c, c, c, c, t, t, t, t, ipeps_tensor,
            np.conj(ipeps_tensor), operator
        ]
        connects = [[6, 1], [7, 2], [3, 8], [4, 5], [1, 13, 18, 7],
                    [2, 12, 17, 3], [8, 14, 15, 4], [5, 11, 16, 6],
                    [9, 13, 11, 14, 12], [10, 18, 16, 15, 17], [10, 9]]
        cont_order = [
            4,
            10,
            6,
            8,
            5,
            16,
            15,
            7,
            2,
            1,
            3,
            18,
            17,
            11,
            14,
            9,
            13,
            12,
        ]
        val = ncon(tensors, connects,
                   cont_order)  # tensortrace: expval_1_1.ttp network 1

        tensors = [c, c, c, c, t, t, t, t, ipeps_tensor, np.conj(ipeps_tensor)]
        connects = [[6, 1], [7, 2], [3, 8], [4, 5], [1, 10, 11, 7],
                    [2, 16, 15, 3], [8, 13, 14, 4], [5, 9, 12, 6],
                    [17, 10, 9, 13, 16], [17, 11, 12, 14, 15]]
        cont_order = [
            5,
            7,
            8,
            4,
            14,
            12,
            1,
            2,
            6,
            11,
            15,
            3,
            10,
            16,
            13,
            9,
            17,
        ]
        normalisation = ncon(
            tensors, connects,
            cont_order)  # tensortrace: expval_1_1.ttp network 2

        return val / normalisation

    elif operator_geometry.shape in [(2, 1),
                                     (1, 2)]:  # nearest-neighbour operator
        #                                                    /   /
        #     c - t - t - c                               - a - a -
        #     |   |   |   |                 |   |         / | / |
        #     t - **B** - t               - **B** -   =     **OP*
        #     |   |   |   |                 |   |           | / | /
        #     c - t - t - c                               - a - a -
        #                                                  /   /

        # computed as horizontal, but due to rotational symmetry, vertical is the same
        tensors = [
            c, c, c, c, t, t, t, t, t, t, ipeps_tensor, ipeps_tensor,
            np.conj(ipeps_tensor),
            np.conj(ipeps_tensor), operator
        ]
        connects = [[10, 1], [3, 4], [5, 6], [8, 9], [1, 22, 23, 2],
                    [2, 26, 27, 3], [4, 17, 18, 5], [6, 25, 28, 7],
                    [7, 21, 24, 8], [9, 15, 20, 10], [11, 22, 15, 21, 16],
                    [13, 26, 16, 25, 17], [12, 23, 20, 24, 19],
                    [14, 27, 19, 28, 18], [12, 14, 11, 13]]
        cont_order = [
            5,
            8,
            3,
            6,
            17,
            25,
            1,
            10,
            18,
            28,
            4,
            26,
            27,
            13,
            14,
            23,
            20,
            7,
            2,
            9,
            12,
            24,
            19,
            22,
            15,
            16,
            11,
            21,
        ]
        val = ncon(tensors, connects,
                   cont_order)  # tensortrace: expval_2_1.ttp

        tensors = [
            c, c, c, c, t, t, t, t, t, t, ipeps_tensor, ipeps_tensor,
            np.conj(ipeps_tensor),
            np.conj(ipeps_tensor)
        ]
        connects = [[10, 1], [3, 4], [5, 6], [8, 9], [1, 18, 19, 2],
                    [2, 22, 23, 3], [4, 13, 14, 5], [6, 21, 24, 7],
                    [7, 17, 20, 8], [9, 11, 16, 10], [26, 18, 11, 17, 12],
                    [25, 22, 12, 21, 13], [26, 19, 16, 20, 15],
                    [25, 23, 15, 24, 14]]
        cont_order = [
            8,
            5,
            6,
            14,
            24,
            10,
            3,
            13,
            21,
            25,
            4,
            22,
            23,
            7,
            1,
            15,
            20,
            9,
            16,
            19,
            2,
            11,
            18,
            12,
            17,
            26,
        ]
        normalisation = ncon(
            tensors, connects,
            cont_order)  # tensortrace: expval_2_1_normalisation.ttp

        return val / normalisation

    else:
        raise NotImplementedError
Пример #8
0
def _variance3(c: np.ndarray, t: np.ndarray, a: np.ndarray) -> float:
    """
    Returns the variance |<aa aa>| - <aa>**2 that would be zero for the fixed point of the RG
    This version also checks if `c` and `t` are an infinite environment of `aa`

    Parameters
    ----------
    c
        The corner matrix c(d, r) with `chi`-dimensional legs
    t
        The half-column / half-row tensor t(l, d, d', r)
    a
        A iPEPS tensor a(p, u, l, d, r)

    Returns
    -------
    var : float
        The variance

    """

    #          c --- c               c --- t --- c                     c --- t --- t --- c
    #          |     |               |     |     |                     |     |     |     |
    #  lr  =   t --- t      ltr  =   t --- aa--- t         lttr   =    t --- aa--- aa--- t
    #          |     |               |     |     |                     |     |     |     |
    #          c --- c               c --- t --- c                     c --- t --- t --- c
    # if RG fixed point is reached then lttr/lr = <tt> = <t>**2 = (ltr/lr)**2

    connects = [[1, 5], [2, 7, 8, 1], [5, 4], [3, 6], [6, 2], [3, 7, 8, 4]]
    cont_order = [
        6,
        5,
        3,
        4,
        1,
        2,
        7,
        8,
    ]
    lr = ncon([c, t, c, c, c, t], connects, cont_order)

    connects = [[1, 10], [2, 14, 17, 1], [11, 4], [3, 13], [12, 2],
                [3, 15, 16, 4], [13, 8, 9, 12], [10, 6, 7, 11],
                [5, 6, 14, 8, 15], [5, 7, 17, 9, 16]]
    cont_order = [
        4,
        3,
        11,
        1,
        2,
        12,
        16,
        7,
        10,
        17,
        13,
        9,
        14,
        8,
        15,
        6,
        5,
    ]
    ltr = ncon([c, t, c, c, c, t, t, t, a, np.conj(a)], connects, cont_order)

    connects = [[1, 15], [2, 21, 26, 1], [17, 4], [3, 20], [18, 2],
                [3, 23, 24, 4], [19, 8, 9, 18], [15, 6, 7, 16],
                [5, 6, 21, 8, 22], [5, 7, 26, 9, 25], [20, 13, 14, 19],
                [16, 11, 12, 17], [10, 11, 22, 13, 23], [10, 12, 25, 14, 24]]
    cont_order = [
        18,
        15,
        20,
        1,
        3,
        7,
        26,
        17,
        14,
        24,
        13,
        23,
        10,
        4,
        11,
        12,
        19,
        16,
        2,
        9,
        25,
        6,
        21,
        5,
        22,
        8,
    ]
    lttr = ncon([c, t, c, c, c, t, t, t, a,
                 np.conj(a), t, t, a,
                 np.conj(a)], connects, cont_order)

    return abs(lttr / lr) - (ltr / lr)**2