Пример #1
0
def onebody_sum_mpo(terms, output_label=None):
    """
    Construct an MPO from a sum of onebody operators, using the recipe from
    the Supplemental Material of [1]_ (Eqs. (3) and (4))

    Parameters
    ---------
    terms : list
        A list containing the terms in the sum. Each term should be 2D 
        array-like, e.g., a rank-two Tensor or numpy array.
    output_label : str, optional
        Specify the label corresponding to the output index. Must be the same
        for each element of `terms`. If not specified the first index is taken 
        to be the output index.

    Returns
    ------
    MatrixProductOperator

    References
    ----------
    .. [1] E. Sanchez-Burillo et al., Phys. Rev. Lett. 113, 263604 (2014)
    """
    tensors = []
    for i, term1 in enumerate(terms):
        if output_label is not None:
            term = term1.copy()
            term.move_index(output_label, 0)
        else:
            term = term1
        if i == 0:
            B = np.zeros(shape=term.shape + (2, ), dtype=complex)
            for k in range(term.shape[0]):
                for l in range(term.shape[1]):
                    B[k, l, :] = [term[k, l], k == l]
            tensors.append(tnc.Tensor(B, ['physout', 'physin', 'right']))
        elif i == len(terms) - 1:
            B = np.zeros(shape=term.shape + (2, ), dtype=complex)
            for k in range(term.shape[0]):
                for l in range(term.shape[1]):
                    B[k, l, :] = [k == l, term[k, l]]
            tensors.append(tnc.Tensor(B, ['physout', 'physin', 'left']))
        else:
            B = np.zeros(shape=term.shape + (2, 2), dtype=complex)
            for k in range(term.shape[0]):
                for l in range(term.shape[1]):
                    B[k, l, :, :] = [[k == l, 0], [term[k, l], k == l]]
            tensors.append(
                tnc.Tensor(B, ['physout', 'physin', 'left', 'right']))
    return onedim.MatrixProductOperator(tensors,
                                        left_label='left',
                                        right_label='right',
                                        physin_label='physin',
                                        physout_label='physout')
Пример #2
0
def init_mps_logical(nsites, basis_state, physdim, left_label='left',
                     right_label='right', phys_label='phys'):
    """
    Create an MPS with `nsites` sites in the logical basis state |ijk..l>.

    Parameters
    ----------
    nsites : int
    basis_state : int or list of ints
        Site `i` will be in the state |`basis_state[i]`> (or simply
        |`basis_state`> if a single int is provided).
    physdim : int or list of ints
    left_label : str
    right_label : str
    phys_label : str
    """
    if not np.iterable(physdim):
        physdim = [physdim] * nsites

    tensors = []
    for j in range(nsites):
        t = np.zeros(physdim[j])
        t[basis_state[j]] = 1.0
        t = tnc.Tensor(t.reshape(physdim[j], 1, 1), [phys_label, left_label,
                                                     right_label])
        tensors.append(t)

    return onedim.MatrixProductState(tensors, left_label=left_label,
                                     right_label=right_label, phys_label=phys_label)
Пример #3
0
def init_mps_allzero(nsites, physdim, left_label='left',
                     right_label='right', phys_label='phys'):
    """
    Create an MPS with `nsites` sites in the "all zero" state |00..0>.

    Parameters
    ----------
    nsites : int
    physdim : int or list of ints
    left_label : str
    right_label : str
    phys_label : str
    """
    if not np.iterable(physdim):
        physdim = [physdim] * nsites

    tensors = []
    for j in range(nsites):
        t = np.zeros(physdim[j])
        t[0] = 1.0
        t = tnc.Tensor(t.reshape(physdim[j], 1, 1), [phys_label, left_label,
                                                     right_label])
        tensors.append(t)

    return onedim.MatrixProductState(tensors, left_label=left_label,
                                     right_label=right_label, phys_label=phys_label)
Пример #4
0
def init_mps_random(nsites,
                    physdim,
                    bonddim=1,
                    left_label='left',
                    right_label='right',
                    phys_label='phys'):
    """
    Create an MPS with `nsites` sites and random tensors with physical 
    dimensions given by `physdim` and bond dimensions given by
    `bonddim`. Open boundary conditions are used. The MPS is not normalized.

    Parameters
    ----------
    nsites : int
    physdim : int or list of ints
    bonddim : int or list of ints, optional
        The nth element of `bonddim` determines the right and left index of
        the tensors at sites n and n+1, respectively. The length of `bonddim`
        should be `nsites`-1. If `bonddim` is an int this is this is used for
        all bonds.
    left_label : str
    right_label : str
    phys_label : str
    """
    if not np.iterable(physdim):
        physdim = [physdim] * nsites
    if not np.iterable(bonddim):
        bonddim = [bonddim] * (nsites - 1)
    bonddim = [1] + bonddim + [1]
    tensors = []
    for i in range(nsites):
        rt = tnc.Tensor(np.random.rand(physdim[i], bonddim[i], bonddim[i + 1]),
                        [phys_label, left_label, right_label])
        # Normalize matrix to avoid norm blowing up
        U, S, V = tnc.tensor_svd(rt, [phys_label, left_label])
        S.data = S.data / S.data[0, 0]
        rt = U["svd_in", ] * S["svd_out", ]
        rt = rt["svd_in", ] * V["svd_out", ]
        tensors.append(rt)
    return onedim.MatrixProductState(tensors,
                                     left_label=left_label,
                                     right_label=right_label,
                                     phys_label=phys_label)