def calc_B1(self): """Calculate the optimal B1 given right gauge-fixing on B2..N and no gauge-fixing on B1. We use the non-norm-preserving K's, since the norm-preservation is not needed elsewhere. It is cleaner to subtract the relevant norm-changing terms from the K's here than to generate all K's with norm-preservation. """ B1 = sp.empty_like(self.A[1]) try: r1_i = self.r[1].inv() except AttributeError: r1_i = mm.invmh(self.r[1]) try: l0_i = self.l[0].inv() except AttributeError: l0_i = mm.invmh(self.l[0]) A0 = self.A[0] A1 = self.A[1] A2 = self.A[2] r1 = self.r[1] r2 = self.r[2] l0 = self.l[0] KLh = mm.H(self.u_gnd_l.K_left - l0 * mm.adot(self.u_gnd_l.K_left, self.r[0])) K2 = self.K[2] - r1 * mm.adot(self.l[1], self.K[2]) C1 = self.C[1] - self.h_expect[1] * self.AA1 C0 = self.C[0] - self.h_expect[0] * self.AA0 for s in xrange(self.q[1]): try: B1[s] = A1[s].dot(r1_i.dot_left(K2)) except AttributeError: B1[s] = A1[s].dot(K2.dot(r1_i)) for t in xrange(self.q[2]): try: B1[s] += C1[s, t].dot(r2.dot(r1_i.dot_left(mm.H(A2[t])))) except AttributeError: B1[s] += C1[s, t].dot(r2.dot(mm.H(A2[t]).dot(r1_i))) B1sbit = KLh.dot(A1[s]) for t in xrange(self.q[0]): B1sbit += mm.H(A0[t]).dot(l0.dot(C0[t,s])) B1[s] += l0_i.dot(B1sbit) rb = sp.zeros_like(self.r[0]) for s in xrange(self.q[1]): rb += B1[s].dot(r1.dot(mm.H(B1[s]))) eta = sp.sqrt(mm.adot(l0, rb)) return B1, eta
def calc_l_r_roots(self, n): """Returns the matrix square roots (and inverses) needed to calculate B. Hermiticity of l[n] and r[n] is used to speed this up. If an exception occurs here, it is probably because these matrices are not longer Hermitian (enough). """ l_sqrt, evd = m.sqrtmh(self.l[n - 1], ret_evd=True) l_sqrt_inv = m.invmh(l_sqrt, evd=evd) r_sqrt, evd = m.sqrtmh(self.r[n], ret_evd=True) r_sqrt_inv = m.invmh(r_sqrt, evd=evd) return l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv
def __init__(self, tdvp, n, KLnm1, tau=1, sanity_checks=False): """ """ self.D = tdvp.D self.q = tdvp.q self.tdvp = tdvp self.n = n self.KLnm1 = KLnm1 self.sanity_checks = sanity_checks self.sanity_tol = 1E-12 d = self.D[n - 1] * self.D[n] * self.q[n] self.shape = (d, d) self.dtype = sp.dtype(tdvp.typ) self.calls = 0 self.tau = tau if n > 1: try: self.lm1_i = tdvp.l[n - 1].inv() except AttributeError: self.lm1_i = m.invmh(tdvp.l[n - 1]) else: self.lm1_i = tdvp.l[n - 1]
def calc_l_r_roots(self, n): """Returns the matrix square roots (and inverses) needed to calculate B. Hermiticity of l[n] and r[n] is used to speed this up. If an exception occurs here, it is probably because these matrices are no longer Hermitian (enough). If l[n] or r[n] are diagonal or the identity, further optimizations are used. """ try: l_sqrt = self.l[n - 1].sqrt() except AttributeError: l_sqrt, evd = mm.sqrtmh(self.l[n - 1], ret_evd=True) try: l_sqrt_inv = l_sqrt.inv() except AttributeError: l_sqrt_inv = mm.invmh(l_sqrt, evd=evd) try: r_sqrt = self.r[n].sqrt() except AttributeError: r_sqrt, evd = mm.sqrtmh(self.r[n], ret_evd=True) try: r_sqrt_inv = r_sqrt.inv() except AttributeError: r_sqrt_inv = mm.invmh(r_sqrt, evd=evd) if self.sanity_checks: if not sp.allclose(mm.mmul(l_sqrt, l_sqrt), self.l[n - 1]): print "Sanity Fail in calc_l_r_roots: Bad l_sqrt_%u" % (n - 1) if not sp.allclose(mm.mmul(r_sqrt, r_sqrt), self.r[n]): print "Sanity Fail in calc_l_r_roots: Bad r_sqrt_%u" % (n) if not sp.allclose(mm.mmul(l_sqrt, l_sqrt_inv), sp.eye(l_sqrt.shape[0])): print "Sanity Fail in calc_l_r_roots: Bad l_sqrt_inv_%u" % (n - 1) if not sp.allclose(mm.mmul(r_sqrt, r_sqrt_inv), sp.eye(r_sqrt.shape[0])): print "Sanity Fail in calc_l_r_roots: Bad r_sqrt_inv_%u" % (n) return l_sqrt, r_sqrt, l_sqrt_inv, r_sqrt_inv
def calc_l_r_roots(self): try: self.l_sqrt = self.l.sqrt() self.l_sqrt_i = self.l_sqrt.inv() except AttributeError: self.l_sqrt, evd = m.sqrtmh(self.l, ret_evd=True) self.l_sqrt_i = m.invmh(self.l_sqrt, evd=evd) try: self.r_sqrt = self.r.sqrt() self.r_sqrt_i = self.r_sqrt.inv() except AttributeError: self.r_sqrt, evd = m.sqrtmh(self.r, ret_evd=True) self.r_sqrt_i = m.invmh(self.r_sqrt, evd=evd) if self.sanity_checks: if not np.allclose(self.l_sqrt.dot(self.l_sqrt), self.l): print "Sanity check failed: l_sqrt is bad!" if not np.allclose(self.l_sqrt.dot(self.l_sqrt_i), np.eye(self.D)): print "Sanity check failed: l_sqrt_i is bad!" if not np.allclose(self.r_sqrt.dot(self.r_sqrt), self.r): print "Sanity check failed: r_sqrt is bad!" if (not np.allclose(self.r_sqrt.dot(self.r_sqrt_i), np.eye(self.D))): print "Sanity check failed: r_sqrt_i is bad!"
def gauge_align(self, other, tol=1E-12): """Gauge-align the state with another. Given two states that differ only by a gauge-transformation and a phase, this makes equalizes the parameter tensors by performing the required transformation. Parameters ---------- other : EvoMPS_MPS_Uniform MPS with which to calculate the per-site fidelity. tol : float Tolerance for detecting per-site fidelity != 1. Returns ------- Nothing if the per-site fidelity is 1. Otherwise: g : ndarray The gauge-transformation matrix used. g_i : ndarray The inverse of g. phi : complex The phase factor. """ d, phi, gR = self.fidelity_per_site(other, full_output=True) if abs(d - 1) > tol: return gR = gR.reshape(self.D, self.D) try: g = other.r.inv().dotleft(gR) except: g = gR.dot(m.invmh(other.r)) gi = la.inv(g) for s in xrange(self.q): self.A[s] = phi.conj() * gi.dot(self.A[s]).dot(g) self.l = m.H(g).dot(self.l.dot(g)) self.r = gi.dot(self.r.dot(m.H(gi))) return g, gi, phi
def calc_B_centre(self): """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and left gauge-fixing on 1..n_centre-1. We use the non-norm-preserving K's, since the norm-preservation is not needed elsewhere. It is cleaner to subtract the relevant norm-changing terms from the K's here than to generate all K's with norm-preservation. """ Bc = sp.empty_like(self.A[self.N_centre]) Nc = self.N_centre try: rc_i = self.r[Nc].inv() except AttributeError: rc_i = mm.invmh(self.r[Nc]) try: lcm1_i = self.l[Nc - 1].inv() except AttributeError: lcm1_i = mm.invmh(self.l[Nc - 1]) Acm1 = self.A[Nc - 1] Ac = self.A[Nc] Acp1 = self.A[Nc + 1] rc = self.r[Nc] rcp1 = self.r[Nc + 1] lcm1 = self.l[Nc - 1] lcm2 = self.l[Nc - 2] #Note: this is a 'bra-vector' K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj( self.K_l[Nc - 1], self.r[Nc - 1]) Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1]) Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1 for s in xrange(self.q[1]): try: #3 Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1)) except AttributeError: Bc[s] = Ac[s].dot(Kcp1.dot(rc_i)) for t in xrange(self.q[2]): #1 try: Bc[s] += Cc[s, t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t])))) except AttributeError: Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i))) Bcsbit = K_l_cm1.dot(Ac[s]) #4 for t in xrange(self.q[0]): #2 Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t, s])) Bc[s] += lcm1_i.dot(Bcsbit) rb = tm.eps_r_noop(rc, Bc, Bc) eta = sp.sqrt(mm.adot(lcm1, rb)) return Bc, eta
def calc_B_centre(self): """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and left gauge-fixing on 1..n_centre-1. We use the non-norm-preserving K's, since the norm-preservation is not needed elsewhere. It is cleaner to subtract the relevant norm-changing terms from the K's here than to generate all K's with norm-preservation. """ Bc = sp.empty_like(self.A[self.N_centre]) Nc = self.N_centre try: rc_i = self.r[Nc].inv() except AttributeError: rc_i = mm.invmh(self.r[Nc]) try: lcm1_i = self.l[Nc - 1].inv() except AttributeError: lcm1_i = mm.invmh(self.l[Nc - 1]) Acm1 = self.A[Nc - 1] Ac = self.A[Nc] Acp1 = self.A[Nc + 1] rc = self.r[Nc] rcp1 = self.r[Nc + 1] lcm1 = self.l[Nc - 1] lcm2 = self.l[Nc - 2] #Note: this is a 'bra-vector' K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj(self.K_l[Nc - 1], self.r[Nc - 1]) Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1]) Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1 for s in xrange(self.q[1]): try: #3 Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1)) except AttributeError: Bc[s] = Ac[s].dot(Kcp1.dot(rc_i)) for t in xrange(self.q[2]): #1 try: Bc[s] += Cc[s, t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t])))) except AttributeError: Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i))) Bcsbit = K_l_cm1.dot(Ac[s]) #4 for t in xrange(self.q[0]): #2 Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t,s])) Bc[s] += lcm1_i.dot(Bcsbit) rb = tm.eps_r_noop(rc, Bc, Bc) eta = sp.sqrt(mm.adot(lcm1, rb)) return Bc, eta