Esempio n. 1
0
 def dotMPS(self, mps, debug=False):
     if debug: print '\n[mpo_class.dotMPS]'
     assert self.nsite == mps.nsite
     mps2 = mps.torank2()
     tmps = self.dot(mps2)
     #
     # Quantum number operations if Qnums exist
     #
     qnums = None
     if self.qnums is not None and mps.qnums is not None:
         if debug: print 'Merge quantum numbers:'
         q1 = self.qnums
         q2 = mps.qnums
         b1 = self.bdim()
         b2 = mps.bdim()
         qnums = [0] * self.nsite
         for ibond in range(self.nsite):
             q1i = self.qnums[ibond]
             q2i = mps.qnums[ibond]
             q12 = mpo_qphys.dpt(q1i, q2i)
             if debug: print 'q12=', q12
             # Some compressions are required to remove negative
             # and large q12 that exceed the allowed qnums.
             qnums[ibond] = copy.deepcopy(q12)
     # Product new MPS
     mps2 = mps_class.class_mps(self.nsite,
                                sites=tmps,
                                qphys=mps.qphys,
                                qnums=qnums)
     return mps2
Esempio n. 2
0
 def qrightCanon(self, thresh=-1.e-12, Dcut=-1, debug=False):
     print '\n[mps_class.qrightCanon]'
     print ' Bdim before: ', self.bdim()
     assert abs(self.norm() - 1.0) < 1.e-8
     sites = self.sites
     nsite = len(sites)
     link = [0] * (nsite - 1)
     sval = [0] * (nsite - 1)
     rmps = [0] * nsite
     qnums = [0] * nsite
     # Current object
     tsite = sites[nsite - 1].copy()
     # Now the symmetry is purely determined from qphys
     qnumr = [copy.deepcopy(self.qphys[0][0])]
     qnums[nsite - 1] = copy.deepcopy(qnumr)
     qphys = copy.deepcopy(self.qphys)
     # rk3
     for isite in range(nsite - 1, -1, -1):
         s = tsite.shape
         d1 = s[0]
         d2 = s[1] * s[2]
         # Combine quantum numbers
         qphys_isite = qphys[isite]
         qnum1 = mpo_qphys.dpt(qphys_isite, qnumr)
         mat = tsite.reshape((d1, d2)).copy()
         classes = qnum1
         if isite != 0:
             dwts, qred, u, sigs, vt = qparser.row_svd(
                 mat.T.copy(), classes, thresh, Dcut)
             bdim = len(sigs)
             print ' isite/bdim=', isite, bdim
             rmps[isite] = u.T.reshape((bdim, s[1], s[2])).copy()
             qnumr = numpy.array(copy.deepcopy(qred))
             qnums[isite - 1] = qnumr.copy()
             # Update next tsite
             tmp = numpy.diag(sigs).dot(vt).T.copy()
             link[isite - 1] = tmp.copy()
             #tsite = numpy.einsum('lur,rs->lus',sites[isite-1],tmp)
             tsite = numpy.tensordot(sites[isite - 1], tmp, axes=([2], [0]))
             sval[isite - 1] = sigs.copy()
         else:
             # Always cut the last one
             dwts, qred, u, sigs, vt = qparser.row_svd(
                 mat.T.copy(), classes, thresh, 1)
             bdim = len(sigs)
             print ' isite/bdim=', isite, bdim
             assert bdim == 1
             rmps[isite] = u.T.reshape((bdim, s[1], s[2])).copy()
         if debug:
             print '-' * 80
             print ' Results[i]:', isite
             print '-' * 80
             print ' dimension:', (d1, d2), '->', bdim
             print ' qred:', qred
             print ' sum of sigs2:', numpy.sum(
                 numpy.array(sigs)**2), ' dwts:', dwts
             print ' sigs:\n', sigs
     # Final
     self.sites = copy.deepcopy(rmps)
     self.qnums = copy.deepcopy(qnums)
     if debug: self.prt()
     print ' Bdim after: ', self.bdim()
     return link, sval
Esempio n. 3
0
 def qleftCanon(self, thresh=-1.e-12, Dcut=-1, debug=False):
     print '\n[mps_class.qleftCanon]'
     print ' Bdim before: ', self.bdim()
     assert abs(self.norm() - 1.0) < 1.e-8
     sites = self.sites
     nsite = len(sites)
     link = [0] * (nsite - 1)
     sval = [0] * (nsite - 1)
     lmps = [0] * nsite
     qnums = [0] * nsite
     # Current object
     tsite = sites[0].copy()
     # Now the symmetry is purely determined from qphys
     qnuml = [copy.deepcopy(self.qphys[0][0])]
     qphys = copy.deepcopy(self.qphys)
     # rk3
     for isite in range(nsite):
         s = tsite.shape
         d1 = s[0] * s[1]
         d2 = s[2]
         # Combine quantum numbers
         qphys_isite = qphys[isite]
         qnum1 = mpo_qphys.dpt(qnuml, qphys_isite)
         mat = tsite.reshape((d1, d2)).copy()
         classes = qnum1
         if isite != nsite - 1:
             dwts, qred, u, sigs, vt = qparser.row_svd(
                 mat, classes, thresh, Dcut)
             bdim = len(sigs)
             print ' isite/bdim=', isite, bdim
             lmps[isite] = u.reshape((s[0], s[1], bdim)).copy()
             qnuml = numpy.array(copy.deepcopy(qred))
             qnums[isite] = qnuml.copy()
             # Update next tsite
             tmp = numpy.diag(sigs).dot(vt)
             link[isite] = tmp.copy()
             #tsite = numpy.einsum('sl,lur->sur',tmp,sites[isite+1])
             tsite = numpy.tensordot(tmp, sites[isite + 1], axes=([1], [0]))
             sval[isite] = sigs.copy()
         else:
             # Otherwise the MPS is zero, or have multiple qnumbers
             # (particle number breaking!)
             dwts, qred, u, sigs, vt = qparser.row_svd(
                 mat, classes, thresh, 1)
             bdim = len(sigs)
             print ' isite/bdim=', isite, bdim
             assert bdim == 1
             lmps[isite] = u.reshape((s[0], s[1], bdim)).copy()
             qnuml = numpy.array(copy.deepcopy(qred))
             qnums[isite] = qnuml.copy()
         if debug:
             print '-' * 80
             print ' Results[i]:', isite
             print '-' * 80
             print ' dimension:', (d1, d2), '->', bdim
             print ' qred:', qred
             print ' sum of sigs2:', numpy.sum(
                 numpy.array(sigs)**2), ' dwts:', dwts
             print ' sigs:\n', sigs
     # Final
     self.sites = copy.deepcopy(lmps)
     self.qnums = copy.deepcopy(qnums)
     if debug: self.prt()
     print ' Bdim after: ', self.bdim()
     return link, sval