Esempio n. 1
0
def svd(tensor,row,new,col,nmax=None,tol=None,returnerr=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,returnerr :
        Please refer to HamiltonianPy.Misc.Linalg.truncatedsvd for details.

    Returns
    -------
    U,S,V : DTensor/STensor
        The result tensor.
    err : float, 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):
        rowlabel,rowrecord=Label.union(row,'__TENSOR_SVD_ROW__',+1,mode=2)
        collabel,colrecord=Label.union(col,'__TENSOR_SVD_COL__',-1,mode=2)
        m=tensor.merge((row,rowlabel,rowrecord),(col,collabel,colrecord)).data
        us,ss,vs,qns=[],[],[],[]
        for (rowqn,colqn),block in m.items():
            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=[rowlabel,new.replace(flow=-1)]).split((rowlabel,row,rowrecord))
        S=DTensor(np.concatenate(Ss),labels=[new])
        V=STensor(Vs,labels=[new.replace(flow=+1),collabel]).split((collabel,col,colrecord))
        if returnerr: err=(temp[nmax:]**2).sum()
    elif tensor.qnon:
        rowlabel,rowpermutation=Label.union(row,'__TENSOR_SVD_ROW__',+1,mode=1)
        collabel,colpermutation=Label.union(col,'__TENSOR_SVD_COL__',-1,mode=1)
        m=tensor.merge((row,rowlabel,rowpermutation),(col,collabel,colpermutation)).data
        rowod,colod=rowlabel.qns.toordereddict(),collabel.qns.toordereddict()
        us,ss,vs,qns=[],[],[],[]
        for qn in filter(lambda key: key in rowod,colod):
            u,s,v=sl.svd(m[rowod[qn],colod[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.toordereddict()
        U=np.zeros((rowlabel.dim,new.dim),dtype=tensor.dtype)
        V=np.zeros((new.dim,collabel.dim),dtype=tensor.dtype)
        for u,v,qn in zip(Us,Vs,od):
            U[rowod[qn],od[qn]]=u
            V[od[qn],colod[qn]]=v
        U=DTensor(U,labels=[rowlabel,new.replace(flow=-1)]).split((rowlabel,row,np.argsort(rowpermutation)))
        S=DTensor(S,labels=[new])
        V=DTensor(V,labels=[new.replace(flow=+1),collabel]).split((collabel,col,np.argsort(colpermutation)))
        if returnerr: err=(temp[nmax:]**2).sum()
    else:
        rowlabel=Label('__TENSOR_SVD_ROW__',qns=np.product([label.dim for label in row]))
        collabel=Label('__TENSOR_SVD_COL__',qns=np.product([label.dim for label in col]))
        m=tensor.merge((row,rowlabel),(col,collabel)).data
        temp=hm.truncatedsvd(m,full_matrices=False,nmax=nmax,tol=tol,returnerr=returnerr,**karg)
        u,s,v=temp[0],temp[1],temp[2]
        new=new.replace(qns=len(s),flow=None)
        U=DTensor(u,labels=[rowlabel,new.replace(flow=0)]).split((rowlabel,row))
        S=DTensor(s,labels=[new])
        V=DTensor(v,labels=[new.replace(flow=0),collabel]).split((collabel,col))
        if returnerr: err=temp[3]
    return (U,S,V,err) if returnerr else (U,S,V)
Esempio n. 2
0
def partitionedsvd(tensor,L,new,R,nmax=None,tol=None,ttype='D',returnerr=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.
    ttype : 'D'/'S', optional
        Tensor type. 'D' for dense and 'S' for sparse.
    nmax,tol,returnerr :
        Please refer to HamiltonianPy.Misc.Linalg.truncatedsvd for details.

    Returns
    -------
    U,S,V : DTensor/STensor
        The Schmitt decomposition of the 1d tensor.
    err : float, optional
        The truncation error.
    '''
    assert tensor.ndim==1 and ttype 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.toordereddict(),R.qns.toordereddict()
        us,ss,vs,qns,count=[],[],[],[],0
        for qn in filter(lambda key: key in lod,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 ttype=='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.toordereddict()
            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 returnerr: err=(temp[nmax:]**2).sum()
    else:
        m=tensor.data.reshape((L.dim,R.dim))
        data=hm.truncatedsvd(m,full_matrices=False,nmax=nmax,tol=tol,returnerr=returnerr)
        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 returnerr: err=data[3]
    return (U,S,V,err) if returnerr else (U,S,V)