Beispiel #1
0
def svd(tensor,
        row,
        new,
        col,
        nmax=None,
        tol=None,
        return_truncation_err=False,
        **karg):
    '''
    Perform the svd.

    Parameters
    ----------
    tensor : DTensor/STensor
        The tensor to be svded.
    row,col : list of Label or int
        The labels or axes to be merged as the row/column during the svd.
    new : Label
        The label for the singular values.
    nmax,tol,return_truncation_err :
        Please refer to HamiltonianPy.Misc.Linalg.truncated_svd for details.

    Returns
    -------
    U,S,V : DTensor/STensor
        The result tensor.
    err : np.float64, optional
        The truncation error.
    '''
    assert len(row) + len(col) == tensor.ndim
    row = [r if isinstance(r, Label) else tensor.label(r) for r in row]
    col = [c if isinstance(c, Label) else tensor.label(c) for c in col]
    if isinstance(tensor, STensor):
        row_label, row_record = Label.union(row,
                                            '__TENSOR_SVD_ROW__',
                                            +1,
                                            mode=2)
        col_label, col_record = Label.union(col,
                                            '__TENSOR_SVD_COL__',
                                            -1,
                                            mode=2)
        m = tensor.merge((row, row_label, row_record),
                         (col, col_label, col_record)).data
        us, ss, vs, qns = [], [], [], []
        for (rowqn, colqn), block in m.iteritems():
            assert rowqn == colqn
            u, s, v = sl.svd(block, full_matrices=False,
                             lapack_driver='gesvd')[0:3]
            us.append(u)
            ss.append(s)
            vs.append(v)
            qns.append(rowqn)
        temp = np.sort(np.concatenate([-s for s in ss]))
        nmax = len(temp) if nmax is None else min(nmax, len(temp))
        tol = temp[nmax - 1] if tol is None else min(-tol, temp[nmax - 1])
        Us, Ss, Vs, contents = {}, [], {}, ([], [])
        for u, s, v, qn in zip(us, ss, vs, qns):
            cut = np.searchsorted(-s, tol, side='right')
            if cut > 0:
                Us[(qn, qn)] = u[:, 0:cut]
                Ss.append(s[0:cut])
                Vs[(qn, qn)] = v[0:cut, :]
                contents[0].append(qn)
                contents[1].append(cut)
        new = new.replace(qns=QuantumNumbers('U',
                                             contents,
                                             protocol=QuantumNumbers.COUNTS),
                          flow=None)
        U = STensor(Us, labels=[row_label, new.replace(flow=-1)]).split(
            (row_label, row, row_record))
        S = DTensor(np.concatenate(Ss), labels=[new])
        V = STensor(Vs, labels=[new.replace(flow=+1), col_label]).split(
            (col_label, col, col_record))
        if return_truncation_err: err = (temp[nmax:]**2).sum()
    elif tensor.qnon:
        row_label, row_permutation = Label.union(row,
                                                 '__TENSOR_SVD_ROW__',
                                                 +1,
                                                 mode=1)
        col_label, col_permutation = Label.union(col,
                                                 '__TENSOR_SVD_COL__',
                                                 -1,
                                                 mode=1)
        m = tensor.merge((row, row_label, row_permutation),
                         (col, col_label, col_permutation)).data
        row_od, col_od = row_label.qns.to_ordereddict(
        ), col_label.qns.to_ordereddict()
        us, ss, vs, qns = [], [], [], []
        for qn in it.ifilter(row_od.has_key, col_od):
            u, s, v = sl.svd(m[row_od[qn], col_od[qn]],
                             full_matrices=False,
                             lapack_driver='gesvd')[0:3]
            us.append(u)
            ss.append(s)
            vs.append(v)
            qns.append(qn)
        temp = np.sort(np.concatenate([-s for s in ss]))
        nmax = len(temp) if nmax is None else min(nmax, len(temp))
        tol = temp[nmax - 1] if tol is None else min(-tol, temp[nmax - 1])
        Us, Ss, Vs, contents = [], [], [], ([], [])
        for u, s, v, qn in zip(us, ss, vs, qns):
            cut = np.searchsorted(-s, tol, side='right')
            if cut > 0:
                Us.append(u[:, 0:cut])
                Ss.append(s[0:cut])
                Vs.append(v[0:cut, :])
                contents[0].append(qn)
                contents[1].append(cut)
        S = np.concatenate(Ss)
        new = new.replace(qns=QuantumNumbers('U',
                                             contents,
                                             protocol=QuantumNumbers.COUNTS),
                          flow=None)
        od = new.qns.to_ordereddict()
        U = np.zeros((row_label.dim, new.dim), dtype=tensor.dtype)
        V = np.zeros((new.dim, col_label.dim), dtype=tensor.dtype)
        for u, v, qn in zip(Us, Vs, od):
            U[row_od[qn], od[qn]] = u
            V[od[qn], col_od[qn]] = v
        U = DTensor(U, labels=[row_label, new.replace(flow=-1)]).split(
            (row_label, row, np.argsort(row_permutation)))
        S = DTensor(S, labels=[new])
        V = DTensor(V, labels=[new.replace(flow=+1), col_label]).split(
            (col_label, col, np.argsort(col_permutation)))
        if return_truncation_err: err = (temp[nmax:]**2).sum()
    else:
        row_label = Label('__TENSOR_SVD_ROW__',
                          qns=np.product([label.dim for label in row]))
        col_label = Label('__TENSOR_SVD_COL__',
                          qns=np.product([label.dim for label in col]))
        m = tensor.merge((row, row_label), (col, col_label)).data
        temp = hm.truncated_svd(m,
                                full_matrices=False,
                                nmax=nmax,
                                tol=tol,
                                return_truncation_err=return_truncation_err,
                                **karg)
        u, s, v = temp[0], temp[1], temp[2]
        new = new.replace(qns=len(s), flow=None)
        U = DTensor(u, labels=[row_label, new.replace(flow=0)]).split(
            (row_label, row))
        S = DTensor(s, labels=[new])
        V = DTensor(v, labels=[new.replace(flow=0), col_label]).split(
            (col_label, col))
        if return_truncation_err: err = temp[3]
    return (U, S, V, err) if return_truncation_err else (U, S, V)
Beispiel #2
0
def partitioned_svd(tensor,
                    L,
                    new,
                    R,
                    mode='D',
                    nmax=None,
                    tol=None,
                    return_truncation_err=False):
    '''
    Partition a 1d-tensor according to L and R and then perform the Schmitt decomposition.

    Parameters
    ----------
    tensor : DTensor
        The tensor to be partitioned_svded.
    L,R : Label
        The left/right part of the partition.
    new : Label
        The label for the singular values.
    mode : 'D'/'S', optional
        'D' for dense and 'S' for sparse.
    nmax,tol,return_truncation_err :
        Please refer to HamiltonianPy.Misc.Linalg.truncated_svd for details.

    Returns
    -------
    U,S,V : DTensor/STensor
        The Schmitt decomposition of the 1d tensor.
    err : np.float64, optional
        The truncation error.
    '''
    assert tensor.ndim == 1 and mode in 'DS'
    if tensor.qnon:
        data, qns = tensor.data, tensor.labels[0].qns
        assert qns.num == 1 and sl.norm(qns.contents) < 10**-6
        lod, rod = L.qns.to_ordereddict(), R.qns.to_ordereddict()
        us, ss, vs, qns, count = [], [], [], [], 0
        for qn in it.ifilter(lod.has_key, rod):
            s1, s2 = lod[qn], rod[qn]
            n1, n2 = s1.stop - s1.start, s2.stop - s2.start
            u, s, v = sl.svd(data[count:count + n1 * n2].reshape((n1, n2)),
                             full_matrices=False,
                             lapack_driver='gesvd')[0:3]
            us.append(u)
            ss.append(s)
            vs.append(v)
            qns.append(qn)
            count += n1 * n2
        temp = np.sort(np.concatenate([-s for s in ss]))
        nmax = len(temp) if nmax is None else min(nmax, len(temp))
        tol = temp[nmax - 1] if tol is None else min(-tol, temp[nmax - 1])
        if mode == 'D':
            Us, Ss, Vs, contents = [], [], [], ([], [])
            for u, s, v, qn in zip(us, ss, vs, qns):
                cut = np.searchsorted(-s, tol, side='right')
                if cut > 0:
                    Us.append(u[:, 0:cut])
                    Ss.append(s[0:cut])
                    Vs.append(v[0:cut, :])
                    contents[0].append(qn)
                    contents[1].append(cut)
            new = new.replace(qns=QuantumNumbers('U', contents,
                                                 QuantumNumbers.COUNTS),
                              flow=None)
            nod = new.qns.to_ordereddict()
            U = np.zeros((L.dim, new.dim), dtype=tensor.dtype)
            S = np.concatenate(Ss)
            V = np.zeros((new.dim, R.dim), dtype=tensor.dtype)
            for u, v, qn in zip(Us, Vs, nod):
                U[lod[qn], nod[qn]] = u
                V[nod[qn], rod[qn]] = v
            U = DTensor(U, labels=[L, new.replace(flow=-1)])
            S = DTensor(S, labels=[new])
            V = DTensor(V, labels=[new.replace(flow=+1), R])
        else:
            Us, Ss, Vs, contents = {}, [], {}, ([], [])
            for u, s, v, qn in zip(us, ss, vs, qns):
                cut = np.searchsorted(-s, tol, side='right')
                if cut > 0:
                    Us[(qn, qn)] = u[:, 0:cut]
                    Ss.append(s[0:cut])
                    Vs[(qn, qn)] = v[0:cut, :]
                    contents[0].append(qn)
                    contents[1].append(cut)
            new = new.replace(qns=QuantumNumbers('U', contents,
                                                 QuantumNumbers.COUNTS),
                              flow=None)
            U = STensor(Us, labels=[L, new.replace(flow=-1)])
            S = DTensor(np.concatenate(Ss), labels=[new])
            V = STensor(Vs, labels=[new.replace(flow=+1), R])
        if return_truncation_err: err = (temp[nmax:]**2).sum()
    else:
        m = tensor.data.reshape((L.dim, R.dim))
        data = hm.truncated_svd(m,
                                full_matrices=False,
                                nmax=nmax,
                                tol=tol,
                                return_truncation_err=return_truncation_err)
        new = new.replace(qns=len(data[1]), flow=None)
        U = DTensor(data[0], labels=[L, new.replace(flow=0)])
        S = DTensor(data[1], labels=[new])
        V = DTensor(data[2], labels=[new.replace(flow=0), R])
        if return_truncation_err: err = data[3]
    return (U, S, V, err) if return_truncation_err else (U, S, V)