def impsgrowth(self, sites, bonds, osvs, qn=0, ttype=None): ''' Infinite MPS growth. Parameters ---------- sites,bonds : list of Label/str The site/bond labels/identifiers of the new mps. osvs : 1d ndarray The old singular values. qn : QuantumNumber, optional The injected quantum number of the new mps. ttype : NOne/'D'/'S', optional Tensor type. 'D' for dense, 'S' for sparse and None for automatic. Returns ------- MPS The imps after growth. ''' if self.nsite > 0: assert self.cut == self.nsite // 2 and self.nsite % 2 == 0 and len( sites) + 1 == len(bonds) ob, nb = self.nsite // 2 + 1, (len(bonds) + 1) // 2 ns = nb - ob cms = self[ob - ns - 1:ob + ns - 1].impsprediction( sites[ob - 1:2 * nb - ob - 1], bonds[ob - 1:2 * nb - ob], osvs, qn=qn, ttype=ttype) lms = MPS([copy(self[pos]) for pos in range(0, self.cut)]) rms = MPS([copy(self[pos]) for pos in range(self.cut, self.nsite)]) lms.relabel(sites[:ob - 1], bonds[:ob]) rms.relabel(sites[-ob + 1:], bonds[-ob:]) rms.qninject(qn) result = MPS(it.chain(lms, cms, rms), Lambda=cms.Lambda, cut=nb - 1, ttype=ttype) else: bonds = copy(bonds) iqns, oqns = (QNS.mono(qn.zero()), QNS.mono(qn)) if isinstance(qn, QN) else (1, 1) bonds[+0] = bonds[+0].replace(qns=iqns) if isinstance( bonds[+0], Label) else Label(bonds[+0], qns=iqns, flow=None) bonds[-1] = bonds[-1].replace(qns=oqns) if isinstance( bonds[-1], Label) else Label(bonds[-1], qns=oqns, flow=None) result = MPS.random(sites, bonds=bonds, cut=len(sites) // 2, nmax=10, ttype=ttype or 'D') return result
def impsgrowth(self,sites,bonds,osvs,qn=0,ttype=None): ''' Infinite MPS growth. Parameters ---------- sites,bonds : list of Label/str The site/bond labels/identifiers of the new mps. osvs : 1d ndarray The old singular values. qn : QuantumNumber, optional The injected quantum number of the new mps. ttype : NOne/'D'/'S', optional Tensor type. 'D' for dense, 'S' for sparse and None for automatic. Returns ------- MPS The imps after growth. ''' if self.nsite>0: assert self.cut==self.nsite//2 and self.nsite%2==0 and len(sites)+1==len(bonds) ob,nb=self.nsite//2+1,(len(bonds)+1)//2 ns=nb-ob cms=self[ob-ns-1:ob+ns-1].impsprediction(sites[ob-1:2*nb-ob-1],bonds[ob-1:2*nb-ob],osvs,qn=qn,ttype=ttype) lms=MPS([copy(self[pos]) for pos in range(0,self.cut)]) rms=MPS([copy(self[pos]) for pos in range(self.cut,self.nsite)]) lms.relabel(sites[:ob-1],bonds[:ob]) rms.relabel(sites[-ob+1:],bonds[-ob:]) rms.qninject(qn) result=MPS(it.chain(lms,cms,rms),Lambda=cms.Lambda,cut=nb-1,ttype=ttype) else: bonds=copy(bonds) iqns,oqns=(QNS.mono(qn.zero()),QNS.mono(qn)) if isinstance(qn,QN) else (1,1) bonds[+0]=bonds[+0].replace(qns=iqns) if isinstance(bonds[+0],Label) else Label(bonds[+0],qns=iqns,flow=None) bonds[-1]=bonds[-1].replace(qns=oqns) if isinstance(bonds[-1],Label) else Label(bonds[-1],qns=oqns,flow=None) result=MPS.random(sites,bonds=bonds,cut=len(sites)//2,nmax=10,ttype=ttype or 'D') return result
def tompo(self, ttype='D', **karg): ''' Convert to the tensor-formatted mpo. Parameters ---------- ttype : 'D'/'S', optional Tensor type. 'D' for dense and 'S' for sparse. karg : dict with keys containing 'nsweep','method' and 'options' Please see MPO.compress for details. Returns ------- MPO The corresponding tensor-formatted MPO. ''' Ms = [] type = self[0][0, 0].site.qns.type if isinstance( self[0][0, 0].site.qns, QuantumNumbers) else None for pos, m in enumerate(self): dim = self.sites[pos].dim L = Label(self.bonds[pos], qns=m.shape[0], flow=0) U = self.sites[pos].replace(prime=True, qns=dim, flow=0) D = self.sites[pos].replace(qns=dim, flow=0) R = Label(self.bonds[pos + 1], qns=m.shape[1], flow=0) Ms.append( DTensor(np.zeros((m.shape[0], dim, dim, m.shape[1]), dtype=self.dtype), labels=[L, U, D, R])) for i, j in it.product(range(m.shape[0]), range(m.shape[1])): Ms[-1].data[i, :, :, j] = m[i, j].matrix result = MPO(Ms) result.compress(**karg) if type is not None: for pos in range(len(result)): lqns, sqns = QuantumNumbers.mono( type.zero()) if pos == 0 else result[pos - 1].labels[ MPO.R].qns, self.sites[pos].qns result[pos].qngenerate(flow=-1, axes=[MPO.L, MPO.U, MPO.D], qnses=[lqns, sqns, sqns], flows=[1, 1, -1]) if ttype == 'S': assert issubclass(type, QuantumNumber) for i, m in enumerate(result): m.qnsort() result[i] = m.tostensor() return result
def tompo(self,degfres,ttype='D'): ''' Convert an optstr to the full-formatted mpo. Parameters ---------- degfres : DegFreTree The tree of the site degrees of freedom. ttype : 'D'/'S', optional Tensor type. 'D' for dense and 'S' for sparse. Returns ------- MPO The corresponding MPO. ''' index=self[0].site.identifier type,layer=degfres.dtype,degfres.layers[degfres.level(index)-1] table,sites,bonds=degfres.table(layer),degfres.labels('S',layer),degfres.labels('O',layer) poses,matrices=set(table[opt.site.identifier] for opt in self),[opt.matrix for opt in self] ms,count=[],0 for pos in range(len(sites)): ndegfre=sites[pos].dim if issubclass(type,QuantumNumbers): L=Label(bonds[pos],qns=QuantumNumbers.mono(type.zero()) if pos==0 else ms[-1].labels[MPO.R].qns,flow=None) U=sites[pos].P D=copy(sites[pos]) R=Label(bonds[pos+1],qns=1,flow=None) else: L=Label(bonds[pos],qns=1,flow=0) U=sites[pos].P.replace(flow=0) D=sites[pos].replace(flow=0) R=Label(bonds[pos+1],qns=1,flow=0) if pos in poses: ms.append(DTensor(np.asarray(matrices[count],dtype=self.dtype).reshape((1,ndegfre,ndegfre,1)),labels=[L,U,D,R])) count+=1 else: ms.append(DTensor(np.identity(ndegfre,dtype=self.dtype).reshape((1,ndegfre,ndegfre,1)),labels=[L,U,D,R])) if issubclass(type,QuantumNumbers): ms[-1].qngenerate(flow=-1,axes=[MPO.L,MPO.U,MPO.D],qnses=[L.qns,U.qns,D.qns],flows=[1,1,-1]) if ttype=='S': assert issubclass(type,QuantumNumbers) for m in ms: m.qnsort() ms=[m.tostensor() for m in ms] return MPO(ms)
def tompo(self,ttype='D',**karg): ''' Convert to the tensor-formatted mpo. Parameters ---------- ttype : 'D'/'S', optional Tensor type. 'D' for dense and 'S' for sparse. karg : dict with keys containing 'nsweep','method' and 'options' Please see MPO.compress for details. Returns ------- MPO The corresponding tensor-formatted MPO. ''' Ms=[] type=self[0][0,0].site.qns.type if isinstance(self[0][0,0].site.qns,QuantumNumbers) else None for pos,m in enumerate(self): dim=self.sites[pos].dim L=Label(self.bonds[pos],qns=m.shape[0],flow=0) U=self.sites[pos].replace(prime=True,qns=dim,flow=0) D=self.sites[pos].replace(qns=dim,flow=0) R=Label(self.bonds[pos+1],qns=m.shape[1],flow=0) Ms.append(DTensor(np.zeros((m.shape[0],dim,dim,m.shape[1]),dtype=self.dtype),labels=[L,U,D,R])) for i,j in it.product(range(m.shape[0]),range(m.shape[1])): Ms[-1].data[i,:,:,j]=m[i,j].matrix result=MPO(Ms) result.compress(**karg) if type is not None: for pos in range(len(result)): lqns,sqns=QuantumNumbers.mono(type.zero()) if pos==0 else result[pos-1].labels[MPO.R].qns,self.sites[pos].qns result[pos].qngenerate(flow=-1,axes=[MPO.L,MPO.U,MPO.D],qnses=[lqns,sqns,sqns],flows=[1,1,-1]) if ttype=='S': assert issubclass(type,QuantumNumber) for i,m in enumerate(result): m.qnsort() result[i]=m.tostensor() return result
def to_mpo(self,**karg): ''' Convert to the tensor-formatted mpo. Parameters ---------- karg : dict with keys containing 'nsweep','method' and 'options' Please see MPO.compress for details. Returns ------- MPO The corresponding tensor-formatted MPO. ''' Ms=[] type=self[0][0,0].site.qns.type if isinstance(self[0][0,0].site.qns,QuantumNumbers) else None for pos,m in enumerate(self): dim=self.sites[pos].dim if type is None: L=self.bonds[pos].replace(qns=m.shape[0],flow=0) U=self.sites[pos].replace(prime=True,flow=0) D=self.sites[pos].replace(flow=0) R=self.bonds[pos+1].replace(qns=m.shape[1],flow=0) else: L=copy(self.bonds[pos]) U=self.sites[pos].P D=self.sites[pos] R=copy(self.bonds[pos+1]) Ms.append(DTensor(np.zeros((m.shape[0],dim,dim,m.shape[1]),dtype=dtype),labels=[L,U,D,R])) for i,j in it.product(xrange(m.shape[0]),xrange(m.shape[1])): Ms[-1][i,:,:,j]=m[i,j].matrix result=MPO(Ms) result.compress(**karg) if type is not None: for pos in xrange(len(result)): lqns,sqns=QuantumNumbers.mono(type.zero()) if pos==0 else result[pos-1].labels[MPO.R].qns,self.sites[pos].qns result[pos].qngenerate(flow=-1,axes=[MPO.L,MPO.U,MPO.D],qnses=[lqns,sqns,sqns],flows=[1,1,-1]) return result
def to_mpo(self,degfres): ''' Convert an optstr to the full-formatted mpo. Parameters ---------- degfres : DegFreTree The tree of the site degrees of freedom. Returns ------- MPO The corresponding MPO. ''' index=self[0].site.identifier type,layer=degfres[index].type if degfres.mode=='QN' else None,degfres.layers[degfres.level(index)-1] table,sites,bonds=degfres.table(layer),degfres.labels('S',layer),degfres.labels('O',layer) poses,matrices=set(table[opt.site.identifier] for opt in self),[opt.matrix for opt in self] ms,count=[],0 for pos in xrange(len(sites)): ndegfre=sites[pos].dim if degfres.mode=='QN': L=bonds[pos].replace(qns=QuantumNumbers.mono(type.zero()) if pos==0 else ms[-1].labels[MPO.R].qns) U=sites[pos].P D=copy(sites[pos]) R=bonds[pos+1].replace(qns=1) else: L=bonds[pos].replace(qns=1,flow=0) U=sites[pos].P.replace(flow=0) D=sites[pos].replace(flow=0) R=bonds[pos+1].replace(qns=1,flow=0) if pos in poses: ms.append(DTensor(np.asarray(matrices[count],dtype=self.dtype).reshape((1,ndegfre,ndegfre,1)),labels=[L,U,D,R])) count+=1 else: ms.append(DTensor(np.identity(ndegfre,dtype=self.dtype).reshape((1,ndegfre,ndegfre,1)),labels=[L,U,D,R])) if degfres.mode=='QN': ms[-1].qngenerate(flow=-1,axes=[MPO.L,MPO.U,MPO.D],qnses=[L.qns,U.qns,D.qns],flows=[1,1,-1]) return MPO(ms)
def random(sites, bonds=None, cut=None, nmax=None, dtype=np.float64): ''' Generate a random mps. Parameters ---------- sites : list of Label/int/QuantumNumbers The labels/number-of-degrees-of-freedom/quantum-numbers of the physical legs. bonds : optional * list of Label The labels of the virtual legs. * 2-list of QuantumNumber The quantum number of the first and last virtual legs. cut : int, optional The index of the connecting link. nmax : int, optional The maximum number of singular values to be kept. dtype : np.float64, np.complex128, optional The data type of the random mps. Returns ------- MPS The random mixed-canonical mps. ''' np.random.seed() sites = [ site if isinstance(site, Label) else Label( '__MPS_RANDOM_S_%s__' % i, qns=site) for i, site in enumerate(sites) ] if bonds is not None and all( isinstance(bond, Label) for bond in bonds): assert len(bonds) == len(sites) + 1 else: if bonds is not None: assert len(bonds) == 2 and isinstance( bonds[0], QN) and isinstance(bonds[1], QN) iqns, oqns = (QNS.mono(bonds[0]), QNS.mono(bonds[1])) if bonds is not None else (1, 1) bonds = [ Label( '__MPS_RANDOM_B_%s__' % i, qns=iqns if i == 0 else oqns if i == len(sites) else None) for i in xrange(len(sites) + 1) ] mode, shape = 'QN' if next(iter(sites)).qnon else 'NB', tuple( [site.dim for site in sites]) if mode == 'QN': result = 0 if dtype in (np.float32, np.float64): coeffs = np.random.random(nmax) else: coeffs = np.random.random(nmax) + 1j * np.random.random(nmax) for k, indices in enumerate( QNS.decomposition([site.qns for site in sites], bonds[-1].qns[0] - bonds[0].qns[0], method='monte carlo', nmax=nmax)): ms = [ np.array( [1.0 if i == index else 0.0 for i in xrange(site.dim)], dtype=dtype) for site, index in zip(sites, indices) ] result += MPS.productstate(ms, sites, copy(bonds)) * coeffs[k] else: ms = [] for i in xrange(len(sites)): if dtype in (np.float32, np.float64): ms.append(np.random.random((nmax, shape[i], nmax))) else: ms.append( np.random.random((nmax, shape[i], nmax)) + 1j * np.random.random((nmax, shape[i], nmax))) result = MPS(mode=mode, ms=ms, sites=sites, bonds=bonds) if cut is None: result.canonicalize(cut=len(sites) / 2, nmax=nmax) result._merge_ABL_() else: result.canonicalize(cut=cut, nmax=nmax) return result
def random(sites, bonds=None, cut=None, nmax=None, ttype='D', dtype=np.float64): ''' Generate a random mps. Parameters ---------- sites : list of Label/int/QuantumNumbers The labels/number-of-degrees-of-freedom/quantum-numbers of the physical legs. bonds : optional * list of Label/str The labels/identifiers of the virtual legs. * 2-list of QuantumNumber The quantum number of the first and last virtual legs. cut : int, optional The index of the connecting link. nmax : int, optional The maximum number of singular values to be kept. 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 mps. Returns ------- MPS The random mixed-canonical mps. ''' np.random.seed() sites = [ site if isinstance(site, Label) else Label( '__MPS_RANDOM_S_%s__' % i, qns=site) for i, site in enumerate(sites) ] if bonds is None or not isinstance(bonds[+0], Label) or not isinstance( bonds[-1], Label): if bonds is not None: iqns = bonds[+0].qns if isinstance( bonds[+0], Label) else bonds[+0] if isinstance( bonds[+0], QNS) else QNS.mono(bonds[+0]) if isinstance( bonds[+0], QN) else 1 oqns = bonds[-1].qns if isinstance( bonds[-1], Label) else bonds[-1] if isinstance( bonds[-1], QNS) else QNS.mono(bonds[-1]) if isinstance( bonds[-1], QN) else 1 else: iqns, oqns = 1, 1 bonds = [ Label('__MPS_RANDOM_B_%s__' % i, None, None) for i in range(len(sites) + 1) ] bonds[+0] = bonds[+0].replace(qns=iqns) bonds[-1] = bonds[-1].replace(qns=oqns) else: assert len(bonds) == len(sites) + 1 bonds = [ bond if isinstance(bond, Label) else Label(bond, None, None) for bond in bonds ] qnon, shape = next(iter(sites)).qnon, tuple( [site.dim for site in sites]) if ttype == 'S': assert qnon if qnon: result = 0 if dtype in (np.float32, np.float64): coeffs = np.random.random(nmax) else: coeffs = np.random.random(nmax) + 1j * np.random.random(nmax) for k, indices in enumerate( QNS.decomposition([site.qns for site in sites], bonds[-1].qns[0] - bonds[+0].qns[0], method='monte carlo', nmax=nmax)): ms = [ np.array( [1.0 if i == index else 0.0 for i in range(site.dim)], dtype=dtype) for site, index in zip(sites, indices) ] result += MPS.productstate(ms, sites, copy(bonds)) * coeffs[k] if ttype == 'S': for m in result: m.qnsort() result = result.tosparse() else: ms = [] for i in range(len(sites)): if dtype in (np.float32, np.float64): ms.append(np.random.random((nmax, shape[i], nmax))) else: ms.append( np.random.random((nmax, shape[i], nmax)) + 1j * np.random.random((nmax, shape[i], nmax))) result = MPS.compose(ms=ms, sites=sites, bonds=bonds) if cut is None: result.canonicalize(cut=len(sites) / 2, nmax=nmax) result._merge_ABL_() else: result.canonicalize(cut=cut, nmax=nmax) return result
def random(sites,bonds=None,cut=None,nmax=None,ttype='D',dtype=np.float64): ''' Generate a random mps. Parameters ---------- sites : list of Label/int/QuantumNumbers The labels/number-of-degrees-of-freedom/quantum-numbers of the physical legs. bonds : optional * list of Label/str The labels/identifiers of the virtual legs. * 2-list of QuantumNumber The quantum number of the first and last virtual legs. cut : int, optional The index of the connecting link. nmax : int, optional The maximum number of singular values to be kept. 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 mps. Returns ------- MPS The random mixed-canonical mps. ''' np.random.seed() sites=[site if isinstance(site,Label) else Label('__MPS_RANDOM_S_%s__'%i,qns=site) for i,site in enumerate(sites)] if bonds is None or not isinstance(bonds[+0],Label) or not isinstance(bonds[-1],Label): if bonds is not None: iqns=bonds[+0].qns if isinstance(bonds[+0],Label) else bonds[+0] if isinstance(bonds[+0],QNS) else QNS.mono(bonds[+0]) if isinstance(bonds[+0],QN) else 1 oqns=bonds[-1].qns if isinstance(bonds[-1],Label) else bonds[-1] if isinstance(bonds[-1],QNS) else QNS.mono(bonds[-1]) if isinstance(bonds[-1],QN) else 1 else: iqns,oqns=1,1 bonds=[Label('__MPS_RANDOM_B_%s__'%i,None,None) for i in range(len(sites)+1)] bonds[+0]=bonds[+0].replace(qns=iqns) bonds[-1]=bonds[-1].replace(qns=oqns) else: assert len(bonds)==len(sites)+1 bonds=[bond if isinstance(bond,Label) else Label(bond,None,None) for bond in bonds] qnon,shape=next(iter(sites)).qnon,tuple([site.dim for site in sites]) if ttype=='S': assert qnon if qnon: result=0 if dtype in (np.float32,np.float64): coeffs=np.random.random(nmax) else: coeffs=np.random.random(nmax)+1j*np.random.random(nmax) for k,indices in enumerate(QNS.decomposition([site.qns for site in sites],bonds[-1].qns[0]-bonds[+0].qns[0],method='monte carlo',nmax=nmax)): ms=[np.array([1.0 if i==index else 0.0 for i in range(site.dim)],dtype=dtype) for site,index in zip(sites,indices)] result+=MPS.productstate(ms,sites,copy(bonds))*coeffs[k] if ttype=='S': for m in result: m.qnsort() result=result.tosparse() else: ms=[] for i in range(len(sites)): if dtype in (np.float32,np.float64): ms.append(np.random.random((nmax,shape[i],nmax))) else: ms.append(np.random.random((nmax,shape[i],nmax))+1j*np.random.random((nmax,shape[i],nmax))) result=MPS.compose(ms=ms,sites=sites,bonds=bonds) if cut is None: result.canonicalize(cut=len(sites)/2,nmax=nmax) result._merge_ABL_() else: result.canonicalize(cut=cut,nmax=nmax) return result
def tompo(self, degfres, ttype='D'): ''' Convert an optstr to the full-formatted mpo. Parameters ---------- degfres : DegFreTree The tree of the site degrees of freedom. ttype : 'D'/'S', optional Tensor type. 'D' for dense and 'S' for sparse. Returns ------- MPO The corresponding MPO. ''' index = self[0].site.identifier type, layer = degfres.dtype, degfres.layers[degfres.level(index) - 1] table, sites, bonds = degfres.table(layer), degfres.labels( 'S', layer), degfres.labels('O', layer) poses, matrices = set(table[opt.site.identifier] for opt in self), [opt.matrix for opt in self] ms, count = [], 0 for pos in range(len(sites)): ndegfre = sites[pos].dim if issubclass(type, QuantumNumbers): L = Label(bonds[pos], qns=QuantumNumbers.mono(type.zero()) if pos == 0 else ms[-1].labels[MPO.R].qns, flow=None) U = sites[pos].P D = copy(sites[pos]) R = Label(bonds[pos + 1], qns=1, flow=None) else: L = Label(bonds[pos], qns=1, flow=0) U = sites[pos].P.replace(flow=0) D = sites[pos].replace(flow=0) R = Label(bonds[pos + 1], qns=1, flow=0) if pos in poses: ms.append( DTensor(np.asarray(matrices[count], dtype=self.dtype).reshape( (1, ndegfre, ndegfre, 1)), labels=[L, U, D, R])) count += 1 else: ms.append( DTensor(np.identity(ndegfre, dtype=self.dtype).reshape( (1, ndegfre, ndegfre, 1)), labels=[L, U, D, R])) if issubclass(type, QuantumNumbers): ms[-1].qngenerate(flow=-1, axes=[MPO.L, MPO.U, MPO.D], qnses=[L.qns, U.qns, D.qns], flows=[1, 1, -1]) if ttype == 'S': assert issubclass(type, QuantumNumbers) for m in ms: m.qnsort() ms = [m.tostensor() for m in ms] return MPO(ms)