Esempio n. 1
0
 def test_associativity(self):
     N,S=2,0.5
     a,b,c,d=np.random.random((N,N)),np.random.random((N,N)),np.random.random((N,N)),np.random.random((N,N))
     p4_2_2=QuantumNumbers.kron([QuantumNumbers.kron([SQNS(S)]*2,signs=(+1,-1))]*2,signs=(+1,+1)).sorted(history=True)[1]
     p41111=QuantumNumbers.kron([SQNS(S)]*4,signs=(+1,-1,+1,-1)).sorted(history=True)[1]
     tmp1,tmp2=np.kron(a,b),np.kron(c,d)
     m1=hm.reorder(np.kron(tmp1,tmp2),permutation=p4_2_2)
     m2=hm.reorder(np.kron(np.kron(np.kron(a,b),c),d),permutation=p41111)
     self.assertAlmostEqual(nl.norm(m2-m1),0.0,delta=10**-14)
Esempio n. 2
0
    def reorder(self, *args):
        '''
        Reorder a dimension of a tensor with a permutation and optionally set a new qns for this dimension.

        Usage: ``tensor.reorder((axis,permutation,<qns>),(axis,permutation,<qns>),...)``
            * axis: int/Label
                The axis of the dimension to be reordered.
            * permutation: 1d ndarray of int
                The permutation array.
            * qns: QuantumNumbers, optional
                The new quantum number collection of the dimension if good quantum numbers are used.

        Returns
        -------
        DTensor
            The reordered tensor.

        Notes
        -----
        If `qns` is not passed, the new qns will be automatically set according to the permutation array.
        '''
        result, qnon = copy(self), self.qnon
        for arg in args:
            assert len(arg) in (2, 3)
            axis, permutation = arg[0], arg[1]
            if permutation is not None:
                axis = self.axis(axis) if isinstance(axis, Label) else axis
                label = result.labels[axis]
                result.labels[axis] = label.replace(
                    qns=arg[2] if len(arg) == 3 else label.qns.
                    reorder(permutation) if qnon else len(permutation))
                result.data = hm.reorder(result.data,
                                         axes=[axis],
                                         permutation=permutation)
        return result
Esempio n. 3
0
    def split(self,*args):
        '''
        Split a label into small ones with an optional permutation.

        Usage: ``tensor.split((old,news,<permutation>),(old,news,<permutation>),...)``
            * old: Label/int
                The label/axis to be split.
            * news: list of Label
                The new labels.
            * permutation: 1d ndarray of int, optional
                The permutation of the quantum number collection of the old label.

        Returns
        -------
        DTensor
            The new tensor.
        '''
        table={(self.axis(arg[0]) if isinstance(arg[0],Label) else arg[0]):i for i,arg in enumerate(args)}
        shape,labels,axes,permutations=(),[],[],[]
        for axis,dim,label in zip(range(self.ndim),self.shape,self.labels):
            if axis in table:
                arg=args[table[axis]]
                assert len(arg) in (2,3)
                shape+=tuple(new.dim for new in arg[1])
                labels.extend(arg[1])
                axes.append(axis)
                permutations.append(arg[2] if len(arg)==3 else None)
            else:
                shape+=(dim,)
                labels.append(label)
        data=self.data
        for axis,permutation in zip(axes,permutations):
            data=hm.reorder(data,axes=[axis],permutation=permutation)
        return DTensor(data.reshape(shape),labels=labels)
Esempio n. 4
0
    def reorder(self,*args):
        '''
        Reorder a dimension of a tensor with a permutation and optionally set a new qns for this dimension.

        Usage: ``tensor.reorder((axis,permutation,<qns>),(axis,permutation,<qns>),...)``
            * axis: int/Label
                The axis of the dimension to be reordered.
            * permutation: 1d ndarray of int
                The permutation array.
            * qns: QuantumNumbers, optional
                The new quantum number collection of the dimension if good quantum numbers are used.

        Returns
        -------
        DTensor
            The reordered tensor.

        Notes
        -----
        If `qns` is not passed, the new qns will be automatically set according to the permutation array.
        '''
        result,qnon=copy(self),self.qnon
        for arg in args:
            assert len(arg) in (2,3)
            axis,permutation=arg[0],arg[1]
            if permutation is not None:
                axis=self.axis(axis) if isinstance(axis,Label) else axis
                label=result.labels[axis]
                result.labels[axis]=label.replace(qns=arg[2] if len(arg)==3 else label.qns.reorder(permutation) if qnon else len(permutation))
                result.data=hm.reorder(result.data,axes=[axis],permutation=permutation)
        return result
Esempio n. 5
0
def fedspcom(blocks, omega):
    '''
    This function composes the zero-temperature single-particle Green's function of a fermionic system from its blocks.

    Parameters
    ----------
    blocks : list of BGF
        The blocks of the Green's function.
    omega : number
        The frequency.

    Returns
    -------
    2d ndarray
        The composed Green's function.
    '''
    assert len(blocks) in (2, 4)
    if len(blocks) == 2:
        return blocks[0].gf(omega).T + blocks[1].gf(omega)
    else:
        gfdw, indsdw = blocks[0].gf(omega).T + blocks[1].gf(
            omega), blocks[0].indices
        gfup, indsup = blocks[2].gf(omega).T + blocks[3].gf(
            omega), blocks[2].indices
        return HM.reorder(HM.block_diag(gfdw, gfup),
                          axes=[0, 1],
                          permutation=np.argsort(
                              np.concatenate((indsdw, indsup))))
Esempio n. 6
0
    def merge(self, *args):
        '''
        Merge some continuous and ascending labels of a tensor into a new one with an optional permutation.

        Usage: ``tensor.merge((olds,new,<permutation>),(olds,new,<permutation>),...)``
            * olds: list of Label/int
                The old labels/axes to be merged.
            * new: Label
                The new label.
            * permutation: 1d ndarray of int, optional
                The permutation of the quantum number collection of the new label.

        Returns
        -------
        DTensor
            The new tensor.
        '''
        permutations = {}
        keep = OrderedDict([(i, i) for i in xrange(self.ndim)])
        labels = OrderedDict([(i, label)
                              for i, label in enumerate(self.labels)])
        for arg in args:
            assert len(arg) in (2, 3)
            olds, new, permutation = (arg[0], arg[1],
                                      None) if len(arg) == 2 else arg
            axes = np.array([
                self.axis(old) if isinstance(old, Label) else old
                for old in olds
            ])
            if len(axes) != max(axes) - min(axes) + 1 or not all(
                    axes[1:] > axes[:-1]):
                raise ValueError(
                    'DTensor merge error: the axes to be merged should be continuous and ascending, please call transpose first.'
                )
            permutations[new] = permutation
            keep[axes[0]] = slice(axes[0], axes[-1] + 1)
            labels[axes[0]] = new
            for axis in axes[1:]:
                keep.pop(axis)
                labels.pop(axis)
        data = self.data.reshape(
            tuple(
                np.product(self.data.shape[ax]
                           ) if isinstance(ax, slice) else self.data.shape[ax]
                for ax in keep.itervalues()))
        labels = labels.values()
        for label, permutation in permutations.iteritems():
            data = hm.reorder(data,
                              axes=[labels.index(label)],
                              permutation=permutation)
        return DTensor(data, labels=labels)
Esempio n. 7
0
    def qnsort(self,history=False):
        '''
        Sort the quantum numbers of all the dimensions of the tensor.

        Returns
        -------
        list of 1d ndarray, optional
            The permutation arrays of the dimensions of the tensor.
            Returned only when ``history`` is True.
        '''
        permutations=[]
        for axis,label in enumerate(self.labels):
            assert label.qnon
            qns,permutation=(label.qns,None) if label.qns.form=='C' else label.qns.sorted(history=True)
            self.data=hm.reorder(self.data,axes=[axis],permutation=permutation)
            self.labels[axis]=label.replace(qns=qns)
            if history: permutations.append(permutation)
        if history: return permutations
Esempio n. 8
0
def fedspcom(blocks,omega):
    '''
    This function composes the zero-temperature single-particle Green's function of a fermionic/hard-core-bosonic system from its blocks.

    Parameters
    ----------
    blocks : list of BGF
        The blocks of the Green's function.
    omega : number
        The frequency.

    Returns
    -------
    2d ndarray
        The composed Green's function.
    '''
    assert len(blocks) in (2,4)
    if len(blocks)==2:
        return blocks[0].gf(omega).T+blocks[1].gf(omega)
    else:
        gfdw,indsdw=blocks[0].gf(omega).T+blocks[1].gf(omega),blocks[0].indices
        gfup,indsup=blocks[2].gf(omega).T+blocks[3].gf(omega),blocks[2].indices
        return HM.reorder(HM.blockdiag(gfdw,gfup),axes=[0,1],permutation=np.argsort(np.concatenate((indsdw,indsup))))
Esempio n. 9
0
    def merge(self,*args):
        '''
        Merge some continuous and ascending labels of a tensor into a new one with an optional permutation.

        Usage: ``tensor.merge((olds,new,<permutation>),(olds,new,<permutation>),...)``
            * olds: list of Label/int
                The old labels/axes to be merged.
            * new: Label
                The new label.
            * permutation: 1d ndarray of int, optional
                The permutation of the quantum number collection of the new label.

        Returns
        -------
        DTensor
            The new tensor.
        '''
        permutations={}
        keep=OrderedDict([(i,i) for i in range(self.ndim)])
        labels=OrderedDict([(i,label) for i,label in enumerate(self.labels)])
        for arg in args:
            assert len(arg) in (2,3)
            olds,new,permutation=(arg[0],arg[1],None) if len(arg)==2 else arg
            axes=np.array([self.axis(old) if isinstance(old,Label) else old for old in olds])
            if len(axes)!=max(axes)-min(axes)+1 or not all(axes[1:]>axes[:-1]):
                raise ValueError('DTensor merge error: the axes to be merged should be continuous and ascending, please call transpose first.')
            permutations[new]=permutation
            keep[axes[0]]=slice(axes[0],axes[-1]+1)
            labels[axes[0]]=new
            for axis in axes[1:]:
                keep.pop(axis)
                labels.pop(axis)
        data=self.data.reshape(tuple(np.product(self.data.shape[ax]) if isinstance(ax,slice) else self.data.shape[ax] for ax in keep.values()))
        labels=list(labels.values())
        for label,permutation in permutations.items():
            data=hm.reorder(data,axes=[labels.index(label)],permutation=permutation)
        return DTensor(data,labels=labels)
Esempio n. 10
0
def random(labels,ttype='D',dtype=np.float64):
    '''
    Construct a random block-structured tensor.

    Parameters
    ----------
    labels : list of Label
        The labels of the random tensor.
    ttype : 'D'/'S', optional
        Tensor type. 'D' for dense and 'S' for sparse.
    dtype : np.float64, np.complex128, optional
        The data type of the random tensor.

    Returns
    -------
    DTensor/STensor
        A random block-structured tensor.
    '''
    assert  ttype in 'DS' and dtype in (np.float32,np.float64,np.complex64,np.complex128)
    np.random.seed()
    if next(iter(labels)).qnon:
        paxes,plbls,maxes,mlbls=[],[],[],[]
        for axis,label in enumerate(labels):
            (paxes if label.flow==1 else maxes).append(axis)
            (plbls if label.flow==1 else mlbls).append(label)
        traxes=np.argsort(list(it.chain(paxes,maxes)))
        if ttype=='D':
            plabel,ppermutation=Label.union(plbls,'__TENSOR_RANDOM_D_+__',+1,mode=1)
            mlabel,mpermutation=Label.union(mlbls,'__TENSOR_RANDOM_D_-__',-1,mode=1)
            data=np.zeros((plabel.dim,mlabel.dim),dtype=dtype)
            pod,mod=plabel.qns.toordereddict(),mlabel.qns.toordereddict()
            for qn in filter(lambda key: key in pod,mod):
                bshape=(pod[qn].stop-pod[qn].start,mod[qn].stop-mod[qn].start)
                data[pod[qn],mod[qn]]=np.random.random(bshape)
                if dtype in (np.complex64,np.complex128):
                    data[pod[qn],mod[qn]]+=1j*np.random.random(bshape)
            for axis,permutation in [(0,np.argsort(ppermutation)),(1,np.argsort(mpermutation))]:
                data=hm.reorder(data,axes=[axis],permutation=permutation)
            data=data.reshape(tuple(label.dim for label in it.chain(plbls,mlbls))).transpose(*traxes)
            result=DTensor(data,labels=labels)
        else:
            plabel,precord=Label.union(plbls,'__TENSOR_RANDOM_S_+__',+1,mode=2)
            mlabel,mrecord=Label.union(mlbls,'__TENSOR_RANDOM_S_-__',-1,mode=2)
            data={}
            ods=[label.qns.toordereddict(protocol=QuantumNumbers.COUNTS) for label in labels]
            pod,mod=plabel.qns.toordereddict(),mlabel.qns.toordereddict()
            for qn in filter(lambda key: key in pod,mod):
                for pqns,mqns in it.product(precord[qn],mrecord[qn]):
                    qns=tuple(it.chain(pqns,mqns))
                    qns=tuple(qns[axis] for axis in traxes)
                    data[qns]=np.zeros(tuple(od[qn] for od,qn in zip(ods,qns)),dtype=dtype)
                    data[qns][...]=np.random.random(data[qns].shape)
                    if dtype in (np.complex64,np.complex128):
                        data[qns][...]+=1j*np.random.random(data[qns].shape)
            result=STensor(data,labels=labels)
    else:
        assert ttype=='D'
        data=np.zeros(tuple(label.dim for label in labels),dtype=dtype)
        data[...]=np.random.random(data.shape)
        if dtype in (np.complex64,np.complex128):
            data[...]+=1j*np.random.random(data.shape)
        result=DTensor(data,labels=labels)
    return result