Example #1
0
def FBFMEB(engine,app):
    '''
    This method calculates the energy spectrums of the spin excitations.
    '''
    path,ne=app.path,min(app.ne or engine.nmatrix,engine.nmatrix)
    if path is not None:
        bz,reciprocals=engine.basis.BZ,engine.lattice.reciprocals
        if not isinstance(path,HP.BaseSpace): path=bz.path(HP.KMap(reciprocals,path) if isinstance(path,str) else path,mode='Q')
        result=np.zeros((path.rank(0),ne+1))
        result[:,0]=path.mesh(0) if path.mesh(0).ndim==1 else np.array(range(path.rank(0)))
        engine.log<<'%s: '%path.rank(0)
        for i,paras in enumerate(path('+')):
            engine.log<<'%s%s'%(i,'..' if i<path.rank(0)-1 else '')
            m=engine.matrix(scalefree=app.scalefree,scaleint=app.scaleint,**paras)
            result[i,1:]=nl.eigvalsh(m)[:ne] if app.method=='eigvalsh' else HM.eigsh(m,k=ne,evon=False)
        engine.log<<'\n'
    else:
        result=np.zeros((2,ne+1))
        result[:,0]=np.array(range(2))
        m=engine.matrix(scalefree=app.scalefree,scaleint=app.scaleint)
        result[0,1:]=nl.eigvalsh(m)[:ne] if app.method=='eigvalsh' else HM.eigsh(m,k=ne,evon=False)
        result[1,1:]=result[0,1:]
    name='%s_%s%s'%(engine.tostr(mask=path.tags),app.name,app.suffix)
    if app.savedata: np.savetxt('%s/%s.dat'%(engine.dout,name),result)
    if app.plot: app.figure('L',result,'%s/%s'%(engine.dout,name))
    if app.returndata: return result
Example #2
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))))
Example #3
0
def VCAGPM(engine,app):
    '''
    This method implements the grand potential based methods.
    '''
    records={}
    def gp(values,keys):
        if tuple(values) not in records:
            engine.cache.pop('ptmesh',None)
            engine.update(**{key:value for key,value in zip(keys,values)})
            engine.rundependences(app.name)
            records[tuple(values)]=engine.records[app.dependences[0]]
        return records[tuple(values)]
    if isinstance(app.BS,HP.BaseSpace):
        mode,nbs,nder,minormax='+',len(app.BS.tags),app.options.get('nder',0),app.options.get('minormax','min')
        result=np.zeros((app.BS.rank(0),nbs+nder+1))
        for i,paras in enumerate(app.BS(mode)):
            result[i,0:nbs]=np.array(list(paras.values()))
            result[i,nbs]=gp(list(paras.values()),list(paras.keys()))
        if nder>0:result[:,nbs+1:]=HM.derivatives(result[:,0],result[:,nbs],ders=list(range(1,nder+1))).T
        index=np.argmin(result[:,-1]) if minormax=='min' else np.argmax(result[:,-1]) if minormax=='max' else np.argmax(np.abs(result[:,-1]))
        engine.log<<'Summary:\n%s\n'%HP.Sheet(
                                cols=           app.BS.tags+['%sgp'%('' if nder==0 else '%s der of '%HP.ordinal(nder-1))],
                                contents=       np.append(result[index,0:nbs],result[index,-1]).reshape((1,-1))
                                )
        name='%s_%s'%(engine.tostr(mask=app.BS.tags),app.name)
        if app.savedata: np.savetxt('%s/%s.dat'%(engine.dout,name),result)
        if app.plot: app.figure('L',result,'%s/%s'%(engine.dout,name),interpolate=True,legend=['%sgp'%('%s der of '%HP.ordinal(k-1) if k>0 else '') for k in range(nder+1)])
        if app.returndata: return result
    else:
        result=HM.fstable(gp,list(app.BS.values()),args=(list(app.BS.keys()),),**app.options)
        engine.log<<'Summary:\n%s\n'%HP.Sheet(cols=list(app.BS.keys())+['niter','nfev','gp'],contents=np.append(result.x,[result.nit,result.nfev,result.fun]).reshape((1,-1)))
        if app.savedata: np.savetxt('%s/%s_%s.dat'%(engine.dout,engine.tostr(mask=list(app.BS.keys())),app.name),np.append(result.x,result.fun))
        if app.returndata: return {key:value for key,value in zip(list(app.BS.keys()),result.x)},result.fun
Example #4
0
def VCAGPM(engine,app):
    '''
    This method implements the grand potential based methods.
    '''
    records={}
    def gp(values,keys):
        if tuple(values) not in records:
            engine.cache.pop('pt_kmesh',None)
            engine.update(**{key:value for key,value in zip(keys,values)})
            engine.rundependences(app.name)
            records[tuple(values)]=engine.records[app.dependences[0]]
        return records[tuple(values)]
    if isinstance(app.BS,HP.BaseSpace):
        mode,nbs,nder,minormax='+',len(app.BS.tags),app.options.get('nder',0),app.options.get('minormax','min')
        result=np.zeros((app.BS.rank(0),nbs+nder+1))
        for i,paras in enumerate(app.BS(mode)):
            result[i,0:nbs]=np.array(paras.values())
            result[i,nbs]=gp(paras.values(),paras.keys())
        if nder>0:result[:,nbs+1:]=HM.derivatives(result[:,0],result[:,nbs],ders=range(1,nder+1)).T
        index=np.argmin(result[:,-1]) if minormax=='min' else np.argmax(result[:,-1]) if minormax=='max' else np.argmax(np.abs(result[:,-1]))
        engine.log<<'Summary:\n%s\n'%HP.Sheet(
                                cols=           app.BS.tags+['%sgp'%('' if nder==0 else '%s der of '%HP.ordinal(nder-1))],
                                contents=       np.append(result[index,0:nbs],result[index,-1]).reshape((1,-1))
                                )
        name='%s_%s'%(engine.tostr(mask=app.BS.tags),app.name)
        if app.savedata: np.savetxt('%s/%s.dat'%(engine.dout,name),result)
        if app.plot: app.figure('L',result,'%s/%s'%(engine.dout,name),interpolate=True,legend=['%sgp'%('%s der of '%HP.ordinal(k-1) if k>0 else '') for k in xrange(nder+1)])
        if app.returndata: return result
    else:
        result=HM.fstable(gp,app.BS.values(),args=(app.BS.keys(),),**app.options)
        engine.log<<'Summary:\n%s\n'%HP.Sheet(cols=app.BS.keys()+['niter','nfev','gp'],contents=np.append(result.x,[result.nit,result.nfev,result.fun]).reshape((1,-1)))
        if app.savedata: np.savetxt('%s/%s_%s.dat'%(engine.dout,engine.tostr(mask=app.BS.keys()),app.name),np.append(result.x,result.fun))
        if app.returndata: return {key:value for key,value in zip(app.BS.keys(),result.x)},result.fun
Example #5
0
    def prepare(self, groundstate, nstep):
        '''
        Prepare the lanczos representation of the block.

        Parameters
        ----------
        groundstate : 1d ndarray
            The ground state.
        nstep : int
            The number of iterations over the whole starting states.
        '''
        matrix, operators = self.controllers['matrix'], self.controllers[
            'operators']
        if self.method == 'S':
            self.controllers['vecs'], self.controllers['lczs'] = [], []
            for operator in operators:
                v0 = operator.dot(groundstate)
                self.controllers['vecs'].append(v0.conjugate())
                self.controllers['lczs'].append(
                    HM.Lanczos(matrix, [v0], maxiter=nstep, keepstate=False))
            self.controllers['vecs'] = np.asarray(self.controllers['vecs'])
            self.controllers['Qs'] = np.zeros(
                (len(operators), len(operators), nstep), dtype=matrix.dtype)
        else:
            self.controllers['lanczos'] = HM.Lanczos(
                matrix,
                v0=[operator.dot(groundstate) for operator in operators],
                maxiter=nstep * len(operators),
                keepstate=False)
Example #6
0
def FBFMEB(engine, app):
    '''
    This method calculates the energy spectrums of the spin excitations.
    '''
    from mpi4py import MPI
    rank = MPI.COMM_WORLD.Get_rank()
    path, ne = app.path, min(app.ne or engine.nmatrix, engine.nmatrix)
    if path is not None:
        bz, reciprocals = engine.basis.BZ, engine.lattice.reciprocals
        if not isinstance(path, HP.BaseSpace):
            path = bz.path(
                HP.KMap(reciprocals, path) if isinstance(path, str) else path,
                mode='Q')
        result = np.zeros((path.rank(0), ne + 1))
        result[:, 0] = path.mesh(0) if path.mesh(0).ndim == 1 else np.array(
            range(path.rank(0)))
        if rank == 0: engine.log << '%s: ' % path.rank(0)
        if app.np in (0, 1, None):
            for i, paras in enumerate(path('+')):
                engine.log << '%s%s' % (i,
                                        '..' if i < path.rank(0) - 1 else '')
                m = engine.matrix(scalefree=app.scalefree,
                                  scaleint=app.scaleint,
                                  **paras)
                result[i, 1:] = nl.eigvalsh(
                    m)[:ne] if app.method == 'eigvalsh' else HM.eigsh(
                        m, k=ne, which='SA', evon=False)
        else:

            def kenergy(paras, engine, app, i):
                engine.log << '%s%s' % (i, '..')
                m = engine.matrix(scalefree=app.scalefree,
                                  scaleint=app.scaleint,
                                  **paras)
                result = nl.eigvalsh(
                    m)[:ne] if app.method == 'eigvalsh' else HM.eigsh(
                        m, k=ne, which='SA', evon=False)
                return result

            for i, data in enumerate(
                    HP.mpirun(kenergy,
                              [(paras, engine, app, i)
                               for i, paras in enumerate(path('+'))])):
                result[i, 1:] = data
        if rank == 0: engine.log << '\n'
    else:
        result = np.zeros((2, ne + 1))
        result[:, 0] = np.array(range(2))
        m = engine.matrix(scalefree=app.scalefree, scaleint=app.scaleint)
        result[0, 1:] = nl.eigvalsh(
            m)[:ne] if app.method == 'eigvalsh' else HM.eigsh(
                m, k=ne, evon=False)
        result[1, 1:] = result[0, 1:]
    if rank == 0:
        name = '%s_%s%s' % (engine.tostr(mask=path.tags), app.name, app.suffix)
        if app.savedata: np.savetxt('%s/%s.dat' % (engine.dout, name), result)
        if app.plot: app.figure('L', result, '%s/%s' % (engine.dout, name))
        if app.returndata: return result
Example #7
0
 def test_algebra(self):
     self.assertAlmostEqual(norm(self.overlap*2.0-(self.mpo*2.0).overlap(self.mps1,self.mps2)),0.0)
     self.assertAlmostEqual(norm(self.overlap*2.0-(2.0*self.mpo).overlap(self.mps1,self.mps2)),0.0)
     self.assertAlmostEqual(norm(self.overlap/2.0-(self.mpo/2.0).overlap(self.mps1,self.mps2)),0.0)
     self.assertAlmostEqual(norm(self.overlap-hm.overlap(self.mps1.state,(self.mpo*self.mps2).state)),0.0)
     self.assertAlmostEqual(norm(hm.overlap(self.mps1.state,self.mopt.dot(self.mopt),self.mps2.state)-(self.mpo*self.mpo).overlap(self.mps1,self.mps2)),0.0)
     another,overlap=self.mpo/2.0,self.overlap/2.0
     self.assertAlmostEqual(norm((self.overlap+overlap)-(self.mpo+another).overlap(self.mps1,self.mps2)),0.0)
     self.assertAlmostEqual(norm((self.overlap-overlap)-(self.mpo-another).overlap(self.mps1,self.mps2)),0.0)
Example #8
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)
Example #9
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
Example #10
0
    def set(self,gse):
        '''
        Set the Lambda matrix, Q matrix and QT matrix of the block.

        Parameters
        ----------
        gse : number
            The groundstate energy.
        '''
        sign=self.controllers['sign']
        if self.method=='S':
            lczs,Qs=self.controllers['lczs'],self.controllers['Qs']
            self.data['niters']=np.zeros(Qs.shape[0],dtype=np.int32)
            self.data['Lambdas']=np.zeros((Qs.shape[0],Qs.shape[2]),dtype=np.float64)
            self.data['Qs']=np.zeros(Qs.shape,dtype=Qs.dtype)
            self.data['QTs']=np.zeros((Qs.shape[0],Qs.shape[2]),dtype=Qs.dtype)
            for i,(lcz,Q) in enumerate(zip(lczs,Qs)):
                if lcz.niter>0:
                    E,V=sl.eigh(lcz.T,eigvals_only=False)
                    self.data['niters'][i]=lcz.niter
                    self.data['Lambdas'][i,0:lcz.niter]=sign*(E-gse)
                    self.data['Qs'][i,:,0:lcz.niter]=Q[:,0:lcz.niter].dot(V)
                    self.data['QTs'][i,0:lcz.niter]=lcz.P[0,0]*V[0,:].conjugate()
        else:
            lanczos=self.controllers['lanczos']
            E,V=sl.eigh(lanczos.T,eigvals_only=False)
            self.data['Lambda']=sign*(E-gse)
            self.data['Q']=lanczos.P[:min(lanczos.nv0,lanczos.niter),:].T.conjugate().dot(V[:min(lanczos.nv0,lanczos.niter),:])
            self.data['QT']=HM.dagger(self.data['Q'])
Example #11
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)
Example #12
0
def fbfmphaseboundary(task,
                      name,
                      parameters,
                      lattice,
                      terms,
                      interactions,
                      ranges,
                      nk=50,
                      scalefree=1.0,
                      scaleint=1.0):
    import HamiltonianPy.FBFM as FB
    import HamiltonianPy.Misc as hm
    assert len(lattice.vectors) == 2
    ns, ne = len(lattice), len(lattice) // 2
    basis = FB.FBFMBasis(BZ=FBZ(lattice.reciprocals, nks=(nk, nk)),
                         filling=Fraction(ne, ns * 2))

    def updateparam(parameters, key, value):
        if key == 't2': parameters['t2'] = value
        if key == 'dU': parameters['Ub'] = parameters['Ua'] - value

    if task == 'nfm-fm: t2' or task == 'nfm-fm: dU':

        def phaseboundary(param):
            updateparam(parameters, task[-2:], param)
            fbfm = fbfmconstruct(name, parameters, basis, lattice, terms,
                                 interactions)
            print(fbfm)
            fbfm.register(
                FB.EB(name='EB%s' % nk,
                      path='H:G-K1,K1-M1,M1-K2,K2-G',
                      ne=nk**2,
                      scalefree=scalefree,
                      scaleint=scaleint,
                      plot=False,
                      savedata=False,
                      run=FB.FBFMEB))
            data = fbfm.records['EB%s' % nk]
            return -1 if np.any(data[:, 1] < -10**-8) else +1
    elif task == 'tfm-fm: t2' or task == 'tfm-fm: dU':

        def phaseboundary(param):
            updateparam(parameters, task[-2:], param)
            fbfm = fbfmconstruct(name, parameters, basis, lattice, terms,
                                 interactions)
            fbfm.register(
                FB.CN(name='CN%s' % nk,
                      BZ=basis.BZ,
                      ns=(0, 1),
                      scalefree=scalefree,
                      scaleint=scaleint,
                      run=FB.FBFMCN))
            data = fbfm.records['CN%s' % nk]
            return -1 if np.abs(data[0]) < 10**-4 else +1
    else:
        raise ValueError("fbfmphaseboundary error: not supported task(%s)." %
                         task)
    result = hm.bisect(phaseboundary, ranges)
    print(result)
    return result
Example #13
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
Example #14
0
    def set(self, gse):
        '''
        Set the Lambda matrix, Q matrix and QT matrix of the block.

        Parameters
        ----------
        gse : number
            The groundstate energy.
        '''
        sign = self.controllers['sign']
        if self.method == 'S':
            lczs, Qs = self.controllers['lczs'], self.controllers['Qs']
            self.data['niters'] = np.zeros(Qs.shape[0], dtype=np.int32)
            self.data['Lambdas'] = np.zeros((Qs.shape[0], Qs.shape[2]),
                                            dtype=np.float64)
            self.data['Qs'] = np.zeros(Qs.shape, dtype=Qs.dtype)
            self.data['QTs'] = np.zeros((Qs.shape[0], Qs.shape[2]),
                                        dtype=Qs.dtype)
            for i, (lcz, Q) in enumerate(zip(lczs, Qs)):
                if lcz.niter > 0:
                    E, V = sl.eigh(lcz.T, eigvals_only=False)
                    self.data['niters'][i] = lcz.niter
                    self.data['Lambdas'][i, 0:lcz.niter] = sign * (E - gse)
                    self.data['Qs'][i, :, 0:lcz.niter] = Q[:,
                                                           0:lcz.niter].dot(V)
                    self.data['QTs'][
                        i, 0:lcz.niter] = lcz.P[0, 0] * V[0, :].conjugate()
        else:
            lanczos = self.controllers['lanczos']
            E, V = sl.eigh(lanczos.T, eigvals_only=False)
            self.data['Lambda'] = sign * (E - gse)
            self.data['Q'] = lanczos.P[:min(
                lanczos.nv0, lanczos.niter), :].T.conjugate().dot(
                    V[:min(lanczos.nv0, lanczos.niter), :])
            self.data['QT'] = HM.dagger(self.data['Q'])
Example #15
0
 def kenergy(paras, engine, app, i):
     engine.log << '%s%s' % (i, '..')
     m = engine.matrix(scalefree=app.scalefree,
                       scaleint=app.scaleint,
                       **paras)
     result = nl.eigvalsh(
         m)[:ne] if app.method == 'eigvalsh' else HM.eigsh(
             m, k=ne, which='SA', evon=False)
     return result
Example #16
0
def test_mpo_spin():
    print 'test_mpo_spin'

    # set the lattice and terms
    lattice = Cylinder(name='WG',
                       block=[np.array([0.0, 0.0]),
                              np.array([0.0, 1.0])],
                       translation=np.array([1.0, 0.0]))([0, 1])
    terms = [SpinTerm('J', 1.0, neighbour=1, indexpacks=Heisenberg())]

    # set the degfres
    S, priority, layers = 0.5, ['scope', 'site', 'orbital',
                                'S'], [('scope', ), ('site', 'orbital', 'S')]
    config = IDFConfig(priority=priority,
                       pids=lattice.pids,
                       map=lambda pid: Spin(S=S))
    table = config.table(mask=[])
    degfres = DegFreTree(mode='QN',
                         layers=layers,
                         priority=priority,
                         leaves=table.keys(),
                         map=lambda index: SQNS(S))

    # set the operators
    opts = Generator(lattice.bonds, config, terms=terms,
                     dtype=np.float64).operators.values()
    optstrs = [OptStr.from_operator(opt, degfres, layers[-1]) for opt in opts]
    mpos = [optstr.to_mpo(degfres) for optstr in optstrs]

    # set the states
    sites, bonds = degfres.labels(mode='S', layer=layers[-1]), degfres.labels(
        mode='B', layer=layers[-1])
    bonds[+0] = bonds[+0].replace(qns=QuantumNumbers.mono(SQN(0.0)))
    bonds[-1] = bonds[-1].replace(qns=QuantumNumbers.mono(SQN(0.0)))
    cut = np.random.randint(0, len(lattice) + 1)
    mps1, mps2 = MPS.random(sites, bonds, cut=cut,
                            nmax=20), MPS.random(sites,
                                                 bonds,
                                                 cut=cut,
                                                 nmax=20)

    # set the reference of test
    mopts = [soptrep(opt, table) for opt in opts]
    overlaps = [hm.overlap(mps1.state, mopt, mps2.state) for mopt in mopts]

    # test optstr
    test_optstr_overlap(optstrs, mps1, mps2, overlaps)
    test_optstr_algebra(optstrs, mps1, mps2, overlaps)
    test_optstr_relayer(optstrs, degfres, mps1, mps2, overlaps)

    # test mpo
    test_mpo_overlap(mpos, mps1, mps2, overlaps)
    test_mpo_algebra(mpos, mps1, mps2, mopts, overlaps)
    test_mpo_relayer(mpos, degfres, mps1, mps2, overlaps)
    print
Example #17
0
def test_mpo_algebra(mpos, mps1, mps2, mopts, overlaps):
    print 'test_mpo_algebra'
    mopt, summation = sum(mopts), sum(overlaps)
    for i, mpo in enumerate(mpos):
        M = mpo if i == 0 else M + mpo

    print 'Compression of MPO'
    print 'Before compression'
    print 'shapes: %s' % (','.join(str(m.shape) for m in M))
    print 'bonds.qnses: %s,%s' % (','.join(
        repr(m.labels[0].qns) for m in M), repr(M[-1].labels[-1].qns))
    M.compress(nsweep=4, method='dpl')
    print 'After compression'
    print 'shapes: %s' % (','.join(str(m.shape) for m in M))
    print 'bonds.qnses: %s,%s' % (','.join(
        repr(m.labels[0].qns) for m in M), repr(M[-1].labels[-1].qns))
    print

    print '+,-*,/ of MPO'
    pos = np.random.randint(len(mpos))
    print 'Addition diff: %s' % norm(summation - M.overlap(mps1, mps2))
    print 'Subtraction diff: %s' % norm(summation - overlaps[pos] -
                                        (M - mpos[pos]).overlap(mps1, mps2))
    print 'Left multiplication diff: %s' % norm(summation * 2.0 -
                                                (M * 2.0).overlap(mps1, mps2))
    print 'Right multiplication diff: %s' % norm(summation * 2.0 -
                                                 (2.0 * M).overlap(mps1, mps2))
    print 'Division diff: %s' % norm(summation / 2.0 -
                                     (M / 2.0).overlap(mps1, mps2))
    print

    print 'MPO*MPS, MPO*MPO'
    print 'mps.cut: %s' % mps2.cut
    print 'MPO*MPS diff: %s' % norm(summation -
                                    hm.overlap(mps1.state, (M * mps2).state))
    print 'MPO*MPO diff: %s' % norm(
        hm.overlap(mps1.state, mopt.dot(mopt), mps2.state) -
        (M * M).overlap(mps1, mps2))
    print
Example #18
0
def FBFMEB(engine, app):
    '''
    This method calculates the energy spectrums of the spin excitations.
    '''
    path, ne = app.path, min(app.ne or engine.nmatrix, engine.nmatrix)
    if path is not None:
        bz, reciprocals = engine.basis.BZ, engine.lattice.reciprocals
        parameters = list(path('+')) if isinstance(path, HP.BaseSpace) else [{
            'k':
            bz[pos]
        } for pos in bz.path(
            HP.KMap(reciprocals, path) if isinstance(path, str) else path,
            mode='I')]
        result = np.zeros((len(parameters), ne + 1))
        result[:, 0] = path.mesh(0) if isinstance(
            path, HP.BaseSpace) and path.mesh(0).ndim == 1 else np.array(
                xrange(len(parameters)))
        engine.log << '%s: ' % len(parameters)
        for i, paras in enumerate(parameters):
            engine.log << '%s%s' % (i, '..' if i < len(parameters) - 1 else '')
            m = engine.matrix(**paras)
            result[i, 1:] = sl.eigh(
                m, eigvals_only=False
            )[0][:ne] if app.method == 'eigh' else HM.eigsh(
                m, k=ne, return_eigenvectors=False)
        engine.log << '\n'
    else:
        result = np.zeros((2, ne + 1))
        result[:, 0] = np.array(xrange(2))
        result[0, 1:] = sl.eigh(
            engine.matrix(),
            eigvals_only=True)[:ne] if app.method == 'eigh' else HM.eigsh(
                engine.matrix(), k=ne, return_eigenvectors=False)
        result[1, 1:] = result[0, 1:]
    name = '%s_%s' % (engine.tostr(
        mask=path.tags if isinstance(path, HP.BaseSpace) else ()), app.name)
    if app.savedata: np.savetxt('%s/%s.dat' % (engine.dout, name), result)
    if app.plot: app.figure('L', result, '%s/%s' % (engine.dout, name))
    if app.returndata: return result
Example #19
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)
Example #20
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))))
Example #21
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
Example #22
0
def deparallelization(tensor,row,new,col,mode='R',zero=10**-8,tol=10**-6):
    '''
    Deparallelize a tensor.

    Parameters
    ----------
    tensor : DTensor
        The tensor to be deparalleled.
    row,col : list of Label or int
        The labels or axes to be merged as the row/column during the deparallelization.
    new : Label
        The label for the new axis after the deparallelization.
    mode : 'R', 'C', optional
        'R' for the deparallelization of the row dimension;
        'C' for the deparallelization of the col dimension.
    zero : float, optional
        The absolute value to identity zero vectors.
    tol : float, optional
        The relative tolerance for rows or columns that can be considered as paralleled.

    Returns
    -------
    M : DTensor
        The deparallelized tensor.
    T : DTensor
        The coefficient matrix that satisfies T*M==m('R') or M*T==m('C').
    '''
    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]
    rlabel=Label.union(row,'__TENSOR_DEPARALLELIZATION_ROW__',+1 if tensor.qnon else 0,mode=0)
    clabel=Label.union(col,'__TENSOR_DEPARALLELIZATION_COL__',-1 if tensor.qnon else 0,mode=0)
    data=tensor.merge((row,rlabel),(col,clabel)).data
    m1,m2,indices=hm.deparallelization(data,mode=mode,zero=zero,tol=tol,returnindices=True)
    if mode=='R':
        new=new.replace(qns=rlabel.qns.reorder(permutation=indices,protocol='EXPANSION') if tensor.qnon else len(indices))
        T=DTensor(m1,labels=[rlabel,new.replace(flow=-1 if tensor.qnon else 0)]).split((rlabel,row))
        M=DTensor(m2,labels=[new.replace(flow=+1 if tensor.qnon else 0),clabel]).split((clabel,col))
        return T,M
    else:
        new=new.replace(qns=clabel.qns.reorder(permutation=indices,protocol='EXPANSION') if tensor.qnon else len(indices))
        M=DTensor(m1,labels=[rlabel,new.replace(flow=-1 if tensor.qnon else 0)]).split((rlabel,row))
        T=DTensor(m2,labels=[new.replace(flow=+1 if tensor.qnon else 0),clabel]).split((clabel,col))
        return M,T
Example #23
0
def EDEL(engine, app):
    '''
    This method calculates the energy levels of the Hamiltonian.
    '''
    name = '%s_%s' % (engine.tostr(mask=app.path.tags), app.name)
    result = np.zeros((app.path.rank(0), app.ns * (app.nder + 1) + 1))
    result[:, 0] = app.path.mesh(0) if len(
        app.path.tags) == 1 and app.path.mesh(0).ndim == 1 else np.array(
            range(app.path.rank(0)))
    for i, paras in enumerate(app.path('+')):
        engine.update(**paras)
        result[i, 1:app.ns + 1] = engine.eigs(
            sector=app.sector,
            k=app.ns,
            evon=False,
            resetmatrix=True if i == 0 else False,
            resettimers=True if i == 0 else False)[1]
        engine.log << '%s\n\n' % engine.timers.tostr(HP.Timers.ALL)
        if app.plot: engine.timers.graph(parents=HP.Timers.ALL)
    else:
        if app.plot:
            engine.timers.cleancache()
            if app.savefig:
                plt.savefig('%s/%s_TIMERS.png' % (engine.log.dir, name))
            plt.close()
    if app.nder > 0:
        for i in range(app.ns):
            result.T[[j * app.ns + i + 1 for j in range(1, app.nder + 1)
                      ]] = HM.derivatives(result[:, 0],
                                          result[:, i + 1],
                                          ders=list(range(1, app.nder + 1)))
    if app.savedata: np.savetxt('%s/%s.dat' % (engine.dout, name), result)
    if app.plot:
        ns = app.ns
        options = {
            'legend':
            [('%s der of ' % HP.ordinal(k // ns - 1) if k // ns > 0 else '') +
             '$E_{%s}$' % (k % ns) for k in range(result.shape[1] - 1)],
            'legendloc':
            'lower right'
        } if ns <= 10 else {}
        app.figure('L', result, '%s/%s' % (engine.dout, name), **options)
    if app.returndata: return result
Example #24
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)
Example #25
0
def EDEL(engine,app):
    '''
    This method calculates the energy levels of the Hamiltonian.
    '''
    name='%s_%s'%(engine.tostr(mask=app.path.tags),app.name)
    result=np.zeros((app.path.rank(0),app.ns*(app.nder+1)+1))
    result[:,0]=app.path.mesh(0) if len(app.path.tags)==1 and app.path.mesh(0).ndim==1 else np.array(range(app.path.rank(0)))
    for i,paras in enumerate(app.path('+')):
        engine.update(**paras)
        result[i,1:app.ns+1]=engine.eigs(sector=app.sector,k=app.ns,evon=False,resetmatrix=True if i==0 else False,resettimers=True if i==0 else False)[1]
        engine.log<<'%s\n\n'%engine.timers.tostr(HP.Timers.ALL)
        if app.plot: engine.timers.graph(parents=HP.Timers.ALL)
    else:
        if app.plot:
            engine.timers.cleancache()
            if app.savefig: plt.savefig('%s/%s_TIMERS.png'%(engine.log.dir,name))
            plt.close()
    if app.nder>0:
        for i in range(app.ns): result.T[[j*app.ns+i+1 for j in range(1,app.nder+1)]]=HM.derivatives(result[:,0],result[:,i+1],ders=list(range(1,app.nder+1)))
    if app.savedata: np.savetxt('%s/%s.dat'%(engine.dout,name),result)
    if app.plot:
        ns=app.ns
        options={'legend':[('%s der of '%HP.ordinal(k//ns-1) if k//ns>0 else '')+'$E_{%s}$'%(k%ns) for k in range(result.shape[1]-1)],'legendloc':'lower right'} if ns<=10 else {}
        app.figure('L',result,'%s/%s'%(engine.dout,name),**options)
    if app.returndata: return result
Example #26
0
    def eigs(self,sector,v0=None,k=1,evon=False,resetmatrix=True,resettimers=True,showes=True):
        '''
        Lowest k eigenvalues and optionally, the corresponding eigenvectors.

        Parameters
        ----------
        sector : any hashable object
            The sector of the eigensystem.
        v0 : 1d ndarray, optional
            The starting vector.
        k : int, optional
            The number of eigenvalues to be computed.
        evon : logical, optional
            True for returning the eigenvectors and False for not.
        resetmatrix : logical, optional
            True for resetting the matrix cache and False for not.
        resettimers : logical, optional
            True for resetting the timers and False for not.
        showes : logical, optional
            True for showing the calculated eigenvalues and False for not.

        Returns
        -------
        sectors : list of any hashable object
            The sectors of the k eigenvalues
        es : 1d ndarray
            Array of k eigenvalues.
        vs : list of 1d ndarray, optional
            List of k eigenvectors.
        '''
        self.log<<'::<Parameters>:: %s\n'%(', '.join('%s=%s'%(key,HP.decimaltostr(value,n=10)) for key,value in self.parameters.items()))
        if resettimers: self.timers.reset()
        if sector is None and len(self.sectors)>1:
            cols=['nopt','dim','nnz','Mt(s)','Et(s)']+(['E%s'%i for i in range(k-1,-1,-1)] if showes else [])
            widths=[14,4,8,10,10,10]+([13]*k if showes else [])
            info=HP.Sheet(corner='sector',rows=[repr(sector) for sector in self.sectors],cols=cols,widths=widths)
            self.log<<'%s\n%s\n%s\n'%(info.frame(),info.coltagstostr(corneron=True),info.division())
            sectors,es,vs=[],[],[]
            for sector in self.sectors:
                with self.timers.get('Matrix'): matrix=self.matrix(sector,reset=resetmatrix)
                V0=None if v0 is None or matrix.shape[0]!=v0.shape[0] else v0
                with self.timers.get('ES'): eigs=HM.eigsh(matrix,v0=V0,k=min(k,matrix.shape[0]),which='SA',evon=evon)
                self.timers.record()
                sectors.extend([sector]*min(k,matrix.shape[0]))
                es.extend(eigs[0] if evon else eigs)
                if evon: vs.extend(eigs[1].T)
                info[(repr(sector),'nopt')]=len(self.operators)
                info[(repr(sector),'dim')]=matrix.shape[0]
                info[(repr(sector),'nnz')]=matrix.nnz
                info[(repr(sector),'Mt(s)')]=self.timers['Matrix'].records[-1],'%.4e'
                info[(repr(sector),'Et(s)')]=self.timers['ES'].records[-1],'%.4e'
                for j in range(k-1,-1,-1): info[(repr(sector),'E%s'%j)]=(es[-1-j],'%.8f') if j<matrix.shape[0] else ''
                self.log<<'%s\n'%info.rowtostr(row=repr(sector))
            indices=np.argsort(es)[:k]
            sectors=[sectors[index] for index in indices]
            es=np.asarray(es)[indices]
            if evon: vs=[vs[index] for index in indices]
            self.log<<'%s\n'%info.frame()
        else:
            if sector is None: sector=next(iter(self.sectors))
            with self.timers.get('Matrix'): matrix=self.matrix(sector,reset=resetmatrix)
            self.log<<'::<Information>:: sector=%r, nopt=%s, dim=%s, nnz=%s, '%(sector,len(self.operators),matrix.shape[0],matrix.nnz)
            V0=None if v0 is None or matrix.shape[0]!=v0.shape[0] else v0
            with self.timers.get('ES'): eigs=HM.eigsh(matrix,v0=V0,k=k,which='SA',evon=evon)
            self.timers.record()
            sectors=[sector]*k
            es=eigs[0] if evon else eigs
            if evon: vs=list(eigs[1].T)
            self.log<<'Mt=%.4es, Et=%.4es'%(self.timers['Matrix'].records[-1],self.timers['ES'].records[-1])
            self.log<<(', evs=%s\n'%(' '.join('%.8f'%e for e in es)) if showes else '\n')
        return (sectors,es,vs) if evon else (sectors,es)
Example #27
0
    def iterate(self,
                log,
                info='',
                sp=True,
                nmax=200,
                tol=10**-6,
                divisor=None,
                piechart=True):
        '''
        The two site dmrg step.

        Parameters
        ----------
        log : Log
            The log file.
        info : str, optional
            The information string passed to self.log.
        sp : logical, optional
            True for state prediction False for not.
        nmax : int, optional
            The maximum singular values to be kept.
        tol : float, optional
            The tolerance of the singular values.
        divisor : int/None, optional
            * When int, it is used as the divisor to calculated the ground state energy per site;
            * When None, the default divisor will be used to calculated the ground state energy per site.
        piechart : logical, optional
            True for showing the piechart of self.timers while False for not.
        '''
        log << '%s(%s)\n%s\n' % (info, self.ttype, self.graph)
        with self.timers.get('Preparation'):
            Ha, Hasite = self.lcontracts[self.cut - 1], self.mpo[self.cut - 1]
            Hb, Hbsite = self.rcontracts[self.cut + 1], self.mpo[self.cut]
            Oa, (La, Sa,
                 Ra) = Hasite.labels[MPO.R], self.mps[self.cut - 1].labels
            Ob, (Lb, Sb, Rb) = Hbsite.labels[MPO.L], self.mps[self.cut].labels
            assert Ra == Lb and Oa == Ob
            Lsys, sysinfo = Label.union([La, Sa],
                                        '__DMRG_ITERATE_SYS__',
                                        flow=+1 if self.mps.qnon else 0,
                                        mode=+2 if self.ttype == 'S' else +1)
            Lenv, envinfo = Label.union([Sb, Rb],
                                        '__DMRG_ITERATE_ENV__',
                                        flow=-1 if self.mps.qnon else 0,
                                        mode=+2 if self.ttype == 'S' else +1)
            subslice = QuantumNumbers.kron(
                [Lsys.qns, Lenv.qns], signs=[1, -1]).subslice(targets=(
                    self.target.zero(), )) if self.mps.qnon else slice(None)
            shape = (len(subslice),
                     len(subslice)) if self.mps.qnon else (Lsys.qns * Lenv.qns,
                                                           Lsys.qns * Lenv.qns)
            Hsys = (Ha * Hasite).transpose([Oa, La.P, Sa.P, La, Sa]).merge(
                ([La.P, Sa.P], Lsys.P.inverse, sysinfo),
                ([La, Sa], Lsys.inverse, sysinfo))
            Henv = (Hbsite * Hb).transpose([Ob, Sb.P, Rb.P, Sb, Rb]).merge(
                ([Sb.P, Rb.P], Lenv.P.inverse, envinfo),
                ([Sb, Rb], Lenv.inverse, envinfo))
            matvec = DMRGMatVec(Hsys, Henv)

            def timedmatvec(v):
                with self.timers.get('matvec'):
                    return matvec(v)

            matrix = hm.LinearOperator(shape=shape,
                                       matvec=timedmatvec,
                                       dtype=Hsys.dtype)
        with self.timers.get('Diagonalization'):
            u, s, v = self.mps[self.cut -
                               1], self.mps.Lambda, self.mps[self.cut]
            v0 = (u * s * v).merge(
                ([La, Sa], Lsys, sysinfo),
                ([Sb, Rb], Lenv, envinfo)).toarray().reshape(
                    -1)[subslice] if sp and s.norm > RZERO else None
            es, vs = hm.eigsh(matrix, which='SA', v0=v0, k=1, tol=tol * 10**-2)
            energy, Psi = es[0], vs[:, 0]
            self.info['Etotal'] = energy, '%.6f'
            self.info['Esite'] = energy / (divisor or self.nsite), '%.8f'
            self.info['nmatvec'] = matrix.count
            self.info['overlap'] = np.inf if v0 is None else np.abs(
                Psi.conjugate().dot(v0) / norm(v0) / norm(Psi)), '%.6f'
        with self.timers.get('Truncation'):
            sysantiinfo = sysinfo if self.ttype == 'S' else np.argsort(
                sysinfo) if self.mps.qnon else None
            envantiinfo = envinfo if self.ttype == 'S' else np.argsort(
                envinfo) if self.mps.qnon else None
            qns = QuantumNumbers.mono(
                self.target.zero(),
                count=len(subslice)) if self.mps.qnon else Lsys.qns * Lenv.qns
            Lgs, new = Label('__DMRG_ITERATE_GS__',
                             qns=qns), Ra.replace(qns=None)
            u, s, v, err = partitionedsvd(Tensor(Psi, labels=[Lgs]),
                                          Lsys,
                                          new,
                                          Lenv,
                                          nmax=nmax,
                                          tol=tol,
                                          ttype=self.ttype,
                                          returnerr=True)
            self.mps[self.cut - 1] = u.split((Lsys, [La, Sa], sysantiinfo))
            self.mps[self.cut] = v.split((Lenv, [Sb, Rb], envantiinfo))
            self.mps.Lambda = s
            self.setlcontract(self.cut)
            self.setrcontract(self.cut)
            self.info['nslice'] = Lgs.dim
            self.info['nbasis'] = s.shape[0]
            self.info['err'] = err, '%.1e'
        self.timers.record()
        log << 'timers of the dmrg:\n%s\n' % self.timers.tostr(Timers.ALL)
        log << 'info of the dmrg:\n%s\n\n' % self.info
        if piechart: self.timers.graph(parents=Timers.ALL)
Example #28
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)
Example #29
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
Example #30
0
 def setUp(self):
     self.init()
     self.overlaps=[hm.overlap(self.mps1.state,mopt,self.mps2.state) for mopt in self.mopts]
     self.optstrs=[OptStr.fromoperator(opt,self.degfres,layer=self.layer) for opt in self.generator.operators]
Example #31
0
    def iterate(self, info='', sp=True, nmax=200, tol=hm.TOL, piechart=True):
        '''
        The two site dmrg step.

        Parameters
        ----------
        info : str, optional
            The information string passed to self.log.
        sp : logical, optional
            True for state prediction False for not.
        nmax : integer, optional
            The maximum singular values to be kept.
        tol : np.float64, optional
            The tolerance of the singular values.
        piechart : logical, optional
            True for showing the piechart of self.timers while False for not.
        '''
        self.log << '%s%s\n%s\n' % (self.state, info, self.graph)
        eold = self.info['Esite']
        with self.timers.get('Preparation'):
            Ha, Hb = self._Hs_['L'][self.mps.cut -
                                    1], self._Hs_['R'][self.mps.nsite -
                                                       self.mps.cut - 1]
            Hasite, Hbsite = self.mpo[self.mps.cut - 1], self.mpo[self.mps.cut]
            La, Sa, Ra = self.mps[self.mps.cut - 1].labels
            Lb, Sb, Rb = self.mps[self.mps.cut].labels
            Oa, Ob = Hasite.labels[MPO.R], Hbsite.labels[MPO.L]
            assert Ra == Lb
            if self.mps.mode == 'QN':
                sysqns, syspt = QuantumNumbers.kron(
                    [La.qns, Sa.qns], signs='++').sort(history=True)
                envqns, envpt = QuantumNumbers.kron(
                    [Sb.qns, Rb.qns], signs='-+').sort(history=True)
                sysantipt, envantipt = np.argsort(syspt), np.argsort(envpt)
                subslice = QuantumNumbers.kron(
                    [sysqns, envqns],
                    signs='+-').subslice(targets=(self.target.zero(), ))
                qns = QuantumNumbers.mono(self.target.zero(),
                                          count=len(subslice))
                self.info['nslice'] = len(subslice)
            else:
                sysqns, syspt, sysantipt = np.product([La.qns,
                                                       Sa.qns]), None, None
                envqns, envpt, envantipt = np.product([Sb.qns,
                                                       Rb.qns]), None, None
                subslice, qns = slice(None), sysqns * envqns
                self.info['nslice'] = qns
            Lpa, Spa, Spb, Rpb = La.prime, Sa.prime, Sb.prime, Rb.prime
            Lsys, Lenv, new = Label('__DMRG_TWO_SITE_STEP_SYS__',
                                    qns=sysqns), Label(
                                        '__DMRG_TWO_SITE_STEP_ENV__',
                                        qns=envqns), Ra.replace(qns=None)
            Lpsys, Lpenv = Lsys.prime, Lenv.prime
            Hsys = contract([Ha, Hasite], engine='tensordot').transpose(
                [Oa, Lpa, Spa, La, Sa]).merge(([Lpa, Spa], Lpsys, syspt),
                                              ([La, Sa], Lsys, syspt))
            Henv = contract([Hbsite, Hb], engine='tensordot').transpose(
                [Ob, Spb, Rpb, Sb, Rb]).merge(([Spb, Rpb], Lpenv, envpt),
                                              ([Sb, Rb], Lenv, envpt))
        if self.matvec == 'csr':
            with self.timers.get('Hamiltonian'):
                if isinstance(subslice, slice):
                    rcs = None
                else:
                    rcs = (np.divide(subslice, Henv.shape[1]),
                           np.mod(subslice, Henv.shape[1]),
                           np.zeros(Hsys.shape[1] * Henv.shape[1],
                                    dtype=np.int64))
                    rcs[2][subslice] = xrange(len(subslice))
                matrix = 0
                for hsys, henv in zip(Hsys, Henv):
                    with self.timers.get('kron'):
                        temp = hm.kron(hsys, henv, rcs=rcs, timers=self.timers)
                    with self.timers.get('sum'):
                        matrix += temp
                self.info['nnz'] = matrix.nnz
                self.info['nz'] = (
                    len(np.argwhere(np.abs(matrix.data) < tol)) * 100.0 /
                    matrix.nnz) if matrix.nnz > 0 else 0, '%1.1f%%'
                self.info['density'] = 1.0 * self.info['nnz'] / self.info[
                    'nslice']**2, '%.1e'
                matrix = hm.LinearOperator(shape=matrix.shape,
                                           matvec=matrix.dot,
                                           dtype=self.dtype)
        else:
            with self.timers.get('Preparation'):
                if self.mps.mode == 'QN':
                    sysod, envod = sysqns.to_ordereddict(
                    ), envqns.to_ordereddict()
                    qnpairs = [[
                        (tuple(qn), tuple(qn - oqn)) for qn in sysqns
                        if tuple(qn) in envod and tuple(qn - oqn) in sysod
                        and tuple(qn - oqn) in envod
                    ] for oqn in Oa.qns]
                    assert len(qnpairs) == len(Hsys)
                    self.cache['vecold'] = np.zeros(Hsys.shape[1] *
                                                    Henv.shape[1],
                                                    dtype=self.dtype)
                    self.cache['vecnew'] = np.zeros(
                        (Hsys.shape[1], Henv.shape[1]), dtype=self.dtype)

                    def matvec(v):
                        with self.timers.get('matvec'):
                            vec, result = self.cache['vecold'], self.cache[
                                'vecnew']
                            vec[subslice] = v
                            result[...] = 0.0
                            vec = vec.reshape((Hsys.shape[1], Henv.shape[1]))
                            for hsys, henv, pairs in zip(Hsys, Henv, qnpairs):
                                for qn1, qn2 in pairs:
                                    result[sysod[qn1], envod[qn1]] += hsys[
                                        sysod[qn1], sysod[qn2]].dot(
                                            vec[sysod[qn2], envod[qn2]]).dot(
                                                henv.T[envod[qn2], envod[qn1]])
                        return result.reshape(-1)[subslice]

                    matrix = hm.LinearOperator(shape=(len(subslice),
                                                      len(subslice)),
                                               matvec=matvec,
                                               dtype=self.dtype)
                else:

                    def matvec(v):
                        v = v.reshape((Hsys.shape[1], Henv.shape[1]))
                        result = np.zeros_like(v)
                        for hsys, henv in zip(Hsys, Henv):
                            result += hsys.dot(v).dot(henv.T)
                        return result.reshape(-1)

                    matrix = hm.LinearOperator(
                        shape=(Hsys.shape[1] * Henv.shape[1],
                               Hsys.shape[1] * Henv.shape[1]),
                        matvec=matvec,
                        dtype=self.dtype)
        with self.timers.get('Diagonalization'):
            u, s, v = self.mps[self.mps.cut -
                               1], self.mps.Lambda, self.mps[self.mps.cut]
            if sp and norm(s) > RZERO:
                v0 = np.asarray(
                    contract([u, s, v], engine='einsum').merge(
                        ([La, Sa], Lsys, syspt),
                        ([Sb, Rb], Lenv, envpt))).reshape(-1)[subslice]
            else:
                v0 = None
            es, vs = hm.eigsh(matrix, which='SA', v0=v0, k=1)
            energy, Psi = es[0], vs[:, 0]
            self.info['Etotal'] = energy, '%.6f'
            self.info['Esite'] = energy / self.mps.nsite, '%.8f'
            self.info['dE/E'] = None if eold is None else (
                norm(self.info['Esite'] - eold) /
                norm(self.info['Esite'] + eold), '%.1e')
            self.info['nmatvec'] = matrix.count
            self.info['overlap'] = np.inf if v0 is None else np.abs(
                Psi.conjugate().dot(v0) / norm(v0) / norm(Psi)), '%.6f'
        with self.timers.get('Truncation'):
            u, s, v, err = Tensor(
                Psi, labels=[Label('__DMRG_TWO_SITE_STEP__', qns=qns)
                             ]).partitioned_svd(Lsys,
                                                new,
                                                Lenv,
                                                nmax=nmax,
                                                tol=tol,
                                                return_truncation_err=True)
            self.mps[self.mps.cut - 1] = u.split((Lsys, [La, Sa], sysantipt))
            self.mps[self.mps.cut] = v.split((Lenv, [Sb, Rb], envantipt))
            self.mps.Lambda = s
            self.set_HL_(self.mps.cut - 1, tol=tol)
            self.set_HR_(self.mps.cut, tol=tol)
            self.info['nbasis'] = len(s)
            self.info['err'] = err, '%.1e'
        self.timers.record()
        self.log << 'timers of the dmrg:\n%s\n' % self.timers.tostr(Timers.ALL)
        self.log << 'info of the dmrg:\n%s\n\n' % self.info
        if piechart: self.timers.graph(parents=Timers.ALL)
Example #32
0
 def setUp(self):
     self.init()
     self.mopt=sum(self.mopts)
     self.overlap=hm.overlap(self.mps1.state,self.mopt,self.mps2.state)
     self.mpo=MPO.fromoperators(self.generator.operators,self.degfres,layer=self.layer,ttype=self.ttype)
Example #33
0
def test_mpo_fermi():
    print 'test_mpo_fermi'

    # set the lattice
    Nscope, Nsite = 2, 2
    a1, a2, points = np.array([1.0, 0.0]), np.array([0.0, 1.0]), []
    for scope in xrange(Nscope):
        for site in xrange(Nsite):
            points.append(
                Point(PID(scope=scope, site=site),
                      rcoord=a1 * site + a2 * scope,
                      icoord=[0.0, 0.0]))
    lattice = Lattice.compose(name='WG', points=points, neighbours=1)
    lattice.plot(pidon=True)

    # set the terms
    terms = [Hopping('t', 1.0, neighbour=1)]

    # set the degfres
    priority, layers = ['scope', 'site', 'orbital', 'spin',
                        'nambu'], [('scope', ), ('site', 'orbital', 'spin')]
    config = IDFConfig(priority=priority)
    for pid in lattice.pids:
        config[pid] = Fermi(nspin=1)
    table = config.table(mask=['nambu'])
    degfres = DegFreTree(mode='QN',
                         layers=layers,
                         priority=priority,
                         leaves=table.keys(),
                         map=lambda index: PQNS(1))

    # set the operators
    opts = Generator(lattice.bonds,
                     config,
                     table=table,
                     terms=terms,
                     dtype=np.complex128).operators.values()
    optstrs = [OptStr.from_operator(opt, degfres, layers[-1]) for opt in opts]
    for i, (opt, optstr) in enumerate(zip(opts, optstrs)):
        print 'operator: %s' % i
        print repr(opt)
        print repr(optstr)
        print
    mpos = [optstr.to_mpo(degfres) for optstr in optstrs]

    # set the states
    sites, bonds = degfres.labels(mode='S', layer=layers[-1]), degfres.labels(
        mode='B', layer=layers[-1])
    bonds[+0] = bonds[+0].replace(qns=QuantumNumbers.mono(PQN(0)))
    bonds[-1] = bonds[-1].replace(
        qns=QuantumNumbers.mono(PQN(Nscope * Nsite / 2)))
    cut = np.random.randint(0, Nsite * Nscope + 1)
    mps1, mps2 = MPS.random(sites, bonds, cut=cut,
                            nmax=20), MPS.random(sites,
                                                 bonds,
                                                 cut=cut,
                                                 nmax=20)

    # set the reference of test
    mopts = [
        foptrep(opt,
                basis=FBasis(nstate=Nscope * Nsite),
                transpose=True,
                dtype=np.complex128) for opt in opts
    ]
    overlaps = [hm.overlap(mps1.state, mopt, mps2.state) for mopt in mopts]

    # test optstr
    test_optstr_overlap(optstrs, mps1, mps2, overlaps)
    test_optstr_algebra(optstrs, mps1, mps2, overlaps)
    test_optstr_relayer(optstrs, degfres, mps1, mps2, overlaps)

    # test mpo
    test_mpo_overlap(mpos, mps1, mps2, overlaps)
    test_mpo_algebra(mpos, mps1, mps2, mopts, overlaps)
    test_mpo_relayer(mpos, degfres, mps1, mps2, overlaps)
    print
Example #34
0
    def iterate(self,log,info='',sp=True,nmax=200,tol=10**-6,divisor=None,piechart=True):
        '''
        The two site dmrg step.

        Parameters
        ----------
        log : Log
            The log file.
        info : str, optional
            The information string passed to self.log.
        sp : logical, optional
            True for state prediction False for not.
        nmax : int, optional
            The maximum singular values to be kept.
        tol : float, optional
            The tolerance of the singular values.
        divisor : int/None, optional
            * When int, it is used as the divisor to calculated the ground state energy per site;
            * When None, the default divisor will be used to calculated the ground state energy per site.
        piechart : logical, optional
            True for showing the piechart of self.timers while False for not.
        '''
        log<<'%s(%s)\n%s\n'%(info,self.ttype,self.graph)
        with self.timers.get('Preparation'):
            Ha,Hasite=self.lcontracts[self.cut-1],self.mpo[self.cut-1]
            Hb,Hbsite=self.rcontracts[self.cut+1],self.mpo[self.cut]
            Oa,(La,Sa,Ra)=Hasite.labels[MPO.R],self.mps[self.cut-1].labels
            Ob,(Lb,Sb,Rb)=Hbsite.labels[MPO.L],self.mps[self.cut].labels
            assert Ra==Lb and Oa==Ob
            Lsys,sysinfo=Label.union([La,Sa],'__DMRG_ITERATE_SYS__',flow=+1 if self.mps.qnon else 0,mode=+2 if self.ttype=='S' else +1)
            Lenv,envinfo=Label.union([Sb,Rb],'__DMRG_ITERATE_ENV__',flow=-1 if self.mps.qnon else 0,mode=+2 if self.ttype=='S' else +1)
            subslice=QuantumNumbers.kron([Lsys.qns,Lenv.qns],signs=[1,-1]).subslice(targets=(self.target.zero(),)) if self.mps.qnon else slice(None)
            shape=(len(subslice),len(subslice)) if self.mps.qnon else (Lsys.qns*Lenv.qns,Lsys.qns*Lenv.qns)
            Hsys=(Ha*Hasite).transpose([Oa,La.P,Sa.P,La,Sa]).merge(([La.P,Sa.P],Lsys.P.inverse,sysinfo),([La,Sa],Lsys.inverse,sysinfo))
            Henv=(Hbsite*Hb).transpose([Ob,Sb.P,Rb.P,Sb,Rb]).merge(([Sb.P,Rb.P],Lenv.P.inverse,envinfo),([Sb,Rb],Lenv.inverse,envinfo))
            matvec=DMRGMatVec(Hsys,Henv)
            def timedmatvec(v):
                with self.timers.get('matvec'): return matvec(v)
            matrix=hm.LinearOperator(shape=shape,matvec=timedmatvec,dtype=Hsys.dtype)
        with self.timers.get('Diagonalization'):
            u,s,v=self.mps[self.cut-1],self.mps.Lambda,self.mps[self.cut]
            v0=(u*s*v).merge(([La,Sa],Lsys,sysinfo),([Sb,Rb],Lenv,envinfo)).toarray().reshape(-1)[subslice] if sp and s.norm>RZERO else None
            es,vs=hm.eigsh(matrix,which='SA',v0=v0,k=1,tol=tol*10**-2)
            energy,Psi=es[0],vs[:,0]
            self.info['Etotal']=energy,'%.6f'
            self.info['Esite']=energy/(divisor or self.nsite),'%.8f'
            self.info['nmatvec']=matrix.count
            self.info['overlap']=np.inf if v0 is None else np.abs(Psi.conjugate().dot(v0)/norm(v0)/norm(Psi)),'%.6f'
        with self.timers.get('Truncation'):
            sysantiinfo=sysinfo if self.ttype=='S' else np.argsort(sysinfo) if self.mps.qnon else None
            envantiinfo=envinfo if self.ttype=='S' else np.argsort(envinfo) if self.mps.qnon else None
            qns=QuantumNumbers.mono(self.target.zero(),count=len(subslice)) if self.mps.qnon else Lsys.qns*Lenv.qns
            Lgs,new=Label('__DMRG_ITERATE_GS__',qns=qns),Ra.replace(qns=None)
            u,s,v,err=partitionedsvd(Tensor(Psi,labels=[Lgs]),Lsys,new,Lenv,nmax=nmax,tol=tol,ttype=self.ttype,returnerr=True)
            self.mps[self.cut-1]=u.split((Lsys,[La,Sa],sysantiinfo))
            self.mps[self.cut]=v.split((Lenv,[Sb,Rb],envantiinfo))
            self.mps.Lambda=s
            self.setlcontract(self.cut)
            self.setrcontract(self.cut)
            self.info['nslice']=Lgs.dim
            self.info['nbasis']=s.shape[0]
            self.info['err']=err,'%.1e'
        self.timers.record()
        log<<'timers of the dmrg:\n%s\n'%self.timers.tostr(Timers.ALL)
        log<<'info of the dmrg:\n%s\n\n'%self.info
        if piechart: self.timers.graph(parents=Timers.ALL)
Example #35
0
    def eigs(self,
             sector,
             v0=None,
             k=1,
             evon=False,
             resetmatrix=True,
             resettimers=True,
             showes=True):
        '''
        Lowest k eigenvalues and optionally, the corresponding eigenvectors.

        Parameters
        ----------
        sector : any hashable object
            The sector of the eigensystem.
        v0 : 1d ndarray, optional
            The starting vector.
        k : int, optional
            The number of eigenvalues to be computed.
        evon : logical, optional
            True for returning the eigenvectors and False for not.
        resetmatrix : logical, optional
            True for resetting the matrix cache and False for not.
        resettimers : logical, optional
            True for resetting the timers and False for not.
        showes : logical, optional
            True for showing the calculated eigenvalues and False for not.

        Returns
        -------
        sectors : list of any hashable object
            The sectors of the k eigenvalues
        es : 1d ndarray
            Array of k eigenvalues.
        vs : list of 1d ndarray, optional
            List of k eigenvectors.
        '''
        self.log << '::<Parameters>:: %s\n' % (', '.join(
            '%s=%s' % (key, HP.decimaltostr(value, n=10))
            for key, value in self.parameters.items()))
        if resettimers: self.timers.reset()
        if sector is None and len(self.sectors) > 1:
            cols = ['nopt', 'dim', 'nnz', 'Mt(s)', 'Et(s)'
                    ] + (['E%s' % i
                          for i in range(k - 1, -1, -1)] if showes else [])
            widths = [14, 4, 8, 10, 10, 10] + ([13] * k if showes else [])
            info = HP.Sheet(corner='sector',
                            rows=[repr(sector) for sector in self.sectors],
                            cols=cols,
                            widths=widths)
            self.log << '%s\n%s\n%s\n' % (info.frame(
            ), info.coltagstostr(corneron=True), info.division())
            sectors, es, vs = [], [], []
            for sector in self.sectors:
                with self.timers.get('Matrix'):
                    matrix = self.matrix(sector, reset=resetmatrix)
                V0 = None if v0 is None or matrix.shape[0] != v0.shape[
                    0] else v0
                with self.timers.get('ES'):
                    eigs = HM.eigsh(matrix,
                                    v0=V0,
                                    k=min(k, matrix.shape[0]),
                                    which='SA',
                                    evon=evon)
                self.timers.record()
                sectors.extend([sector] * min(k, matrix.shape[0]))
                es.extend(eigs[0] if evon else eigs)
                if evon: vs.extend(eigs[1].T)
                info[(repr(sector), 'nopt')] = len(self.operators)
                info[(repr(sector), 'dim')] = matrix.shape[0]
                info[(repr(sector), 'nnz')] = matrix.nnz
                info[(repr(sector),
                      'Mt(s)')] = self.timers['Matrix'].records[-1], '%.4e'
                info[(repr(sector),
                      'Et(s)')] = self.timers['ES'].records[-1], '%.4e'
                for j in range(k - 1, -1, -1):
                    info[(repr(sector),
                          'E%s' % j)] = (es[-1 - j],
                                         '%.8f') if j < matrix.shape[0] else ''
                self.log << '%s\n' % info.rowtostr(row=repr(sector))
            indices = np.argsort(es)[:k]
            sectors = [sectors[index] for index in indices]
            es = np.asarray(es)[indices]
            if evon: vs = [vs[index] for index in indices]
            self.log << '%s\n' % info.frame()
        else:
            if sector is None: sector = next(iter(self.sectors))
            with self.timers.get('Matrix'):
                matrix = self.matrix(sector, reset=resetmatrix)
            self.log << '::<Information>:: sector=%r, nopt=%s, dim=%s, nnz=%s, ' % (
                sector, len(self.operators), matrix.shape[0], matrix.nnz)
            V0 = None if v0 is None or matrix.shape[0] != v0.shape[0] else v0
            with self.timers.get('ES'):
                eigs = HM.eigsh(matrix, v0=V0, k=k, which='SA', evon=evon)
            self.timers.record()
            sectors = [sector] * k
            es = eigs[0] if evon else eigs
            if evon: vs = list(eigs[1].T)
            self.log << 'Mt=%.4es, Et=%.4es' % (
                self.timers['Matrix'].records[-1],
                self.timers['ES'].records[-1])
            self.log << (', evs=%s\n' %
                         (' '.join('%.8f' % e
                                   for e in es)) if showes else '\n')
        return (sectors, es, vs) if evon else (sectors, es)
Example #36
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)