def _update_after_truncate(self, n_last_trunc, old_l, n_first_trunc, old_r): if self.canonical_form == 'right': self.r[0][0, 0] = 1 for n in xrange(1, self.N): self.l[n] = m.simple_diag_matrix(old_l[n].diag[-self.D[n]:], dtype=self.typ) self.l[self.N][0, 0] = 1 for n in xrange(self.N - 1, n_last_trunc - 1, -1): self.r[n] = m.eyemat(self.D[n], dtype=self.typ) self.calc_r(n_high=n_last_trunc - 1) else: self.l[0][0, 0] = 1 for n in xrange(1, self.N): self.r[n] = m.simple_diag_matrix(old_r[n].diag[-self.D[n]:], dtype=self.typ) self.r[0][0, 0] = 1 for n in xrange(1, n_first_trunc): self.l[n] = m.eyemat(self.D[n], dtype=self.typ) self.calc_l(n_low=n_first_trunc) self.simple_renorm()
def _update_after_truncate(self, n_last_trunc, old_l, n_first_trunc, old_r): if self.canonical_form == 'right': self.r[0][0, 0] = 1 for n in xrange(1, self.N): self.l[n] = m.simple_diag_matrix(old_l[n].diag[-self.D[n]:], dtype=self.typ) self.l[self.N][0, 0] = 1 for n in xrange(self.N - 1, n_last_trunc - 1, - 1): self.r[n] = m.eyemat(self.D[n], dtype=self.typ) self.calc_r(n_high=n_last_trunc - 1) else: self.l[0][0, 0] = 1 for n in xrange(1, self.N): self.r[n] = m.simple_diag_matrix(old_r[n].diag[-self.D[n]:], dtype=self.typ) self.r[0][0, 0] = 1 for n in xrange(1, n_first_trunc): self.l[n] = m.eyemat(self.D[n], dtype=self.typ) self.calc_l(n_low=n_first_trunc) self.simple_renorm()
def _restore_CF_diag(self, dbg=False): nc = self.N_centre #Want: r[0 <= n < nc] diagonal Ui = sp.eye(self.D[nc], dtype=self.typ) for n in xrange(nc, 0, -1): self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r(self.A[n], self.r[n], Ui, sanity_checks=self.sanity_checks) Ui = Um1_i #Now U is U_0 U = Um1 for s in xrange(self.q[0]): self.uni_l.A[0][s] = U.dot(self.uni_l.A[0][s]) self.uni_l.A[-1][s] = self.uni_l.A[-1][s].dot(Ui) self.uni_l.r[-1] = U.dot(self.uni_l.r[-1].dot(U.conj().T)) #And now: l[nc <= n <= N] diagonal if dbg: Um1 = sp.eye(self.D[nc - 1], dtype=self.typ) else: Um1 = mm.eyemat(self.D[nc - 1], dtype=self.typ) #FIXME: This only works if l[nc - 1] is a special matrix type for n in xrange(nc, self.N + 1): self.l[n], U, Ui = tm.restore_RCF_l(self.A[n], self.l[n - 1], Um1, sanity_checks=self.sanity_checks) Um1 = U #Now, Um1 = U_N Um1_i = Ui for s in xrange(self.q[0]): self.uni_r.A[0][s] = Um1.dot(self.uni_r.A[0][s]) self.uni_r.A[-1][s] = self.uni_r.A[-1][s].dot(Um1_i) self.uni_r.l[-1] = Um1_i.conj().T.dot(self.uni_r.l[-1].dot(Um1_i))
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''): """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. Uses a reduced QR decomposition to avoid inverting anything explicity. Parameters ---------- A : sequence of ndarray The parameter tensors for a sequence of sites [None, A1, A2,..., AN]. The first entry is ignored so that the indices match up with r. r : sequence of ndarray or objects with array interface The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is used for sanity checks. GN : ndarray or scalar Initial right gauge transformation matrix for site N. Only needed when used as part of a larger transformation. sanity_checks : bool (False) Whether to perform additional sanity checks. sc_data : string A string to be appended to sanity check log messages. """ assert len(A) == len(r), 'A and r must have the same length!' if GN is None: Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype) else: Gh = GN.conj().T for n in xrange(len(A) - 1, 0, -1): q, Dm1, D = A[n].shape AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape( (q * D, Dm1)) Q, R = la.qr(AG, mode='economic') A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1)) Gh = R r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype) if sanity_checks: r_nm1_ = eps_r_noop(r[n], A[n], A[n]) if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r[n - 1]), sc_data) return Gh.conj().T
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''): """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. Uses a reduced QR decomposition to avoid inverting anything explicity. Parameters ---------- A : sequence of ndarray The parameter tensors for a sequence of sites [None, A1, A2,..., AN]. The first entry is ignored so that the indices match up with r. r : sequence of ndarray or objects with array interface The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is used for sanity checks. GN : ndarray or scalar Initial right gauge transformation matrix for site N. Only needed when used as part of a larger transformation. sanity_checks : bool (False) Whether to perform additional sanity checks. sc_data : string A string to be appended to sanity check log messages. """ assert len(A) == len(r), 'A and r must have the same length!' if GN is None: Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype) else: Gh = GN.conj().T for n in xrange(len(A) - 1, 0, -1): q, Dm1, D = A[n].shape AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape((q * D, Dm1)) Q, R = la.qr(AG, mode='economic') A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1)) Gh = R r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype) if sanity_checks: r_nm1_ = eps_r_noop(r[n], A[n], A[n]) if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r[n - 1]), sc_data) return Gh.conj().T
def restore_LCF_l(A, lm1, Gm1, sanity_checks=False, zero_tol=1E-15): if Gm1 is None: GhGm1 = lm1 else: GhGm1 = Gm1.conj().T.dot(lm1.dot(Gm1)) M = eps_l_noop(GhGm1, A, A) G, Gi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, sanity_checks=sanity_checks) if Gm1 is None: Gm1 = G if sanity_checks: if new_D == A.shape[2]: eye = sp.eye(A.shape[2]) else: eye = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D), np.ones(new_D)), dtype=A.dtype) if not sp.allclose(G.dot(Gi), eye, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_LCF_l!: Bad GT!") for s in xrange(A.shape[0]): A[s] = Gm1.dot(A[s]).dot(Gi) if new_D == A.shape[2]: l = mm.eyemat(A.shape[2], A.dtype) else: l = mm.simple_diag_matrix(np.append(np.zeros(A.shape[2] - new_D), np.ones(new_D)), dtype=A.dtype) if sanity_checks: lm1_ = mm.eyemat(A.shape[1], A.dtype) l_ = eps_l_noop(lm1_, A, A) if not sp.allclose(l_, l.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_LCF_l!: l is bad") log.warning(la.norm(l_ - l)) return l, G, Gi
def restore_LCF_l_seq(A, l, G0=None, sanity_checks=False, sc_data=''): """Transforms a sequence of A[n]'s to obtain l[n] = eye(D). Implements the condition for left-orthonormalization. Uses a reduced QR (RQ) decomposition to avoid inverting anything explicity. Parameters ---------- A : sequence of ndarray The parameter tensors for a sequence of sites [None, A1, A2,..., AN]. The first entry is ignored so that the indices match up with l. l : sequence of ndarray or objects with array interface The matrices [l0, l1, l2,..., lN], where l0 will not be changed, but is used for sanity checks. G0 : ndarray or scalar Initial left gauge transformation matrix for site 0. Only needed when used as part of a larger transformation. sanity_checks : bool (False) Whether to perform additional sanity checks. sc_data : string A string to be appended to sanity check log messages. """ if G0 is None: G = mm.eyemat(A[1].shape[1], dtype=A[1].dtype) else: G = G0 for n in xrange(1, len(A)): q, Dm1, D = A[n].shape GA = sp.array([G.dot(As) for As in A[n]]) GA = GA.reshape((q * Dm1, D)) Q, G = la.qr(GA, mode='economic') A[n] = Q.reshape((q, Dm1, D)) l[n] = mm.eyemat(D, dtype=A[n].dtype) if sanity_checks: l_ = eps_l_noop(l[n - 1], A[n], A[n]) if not sp.allclose(l_, l[n].A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_LCF_l_seq!: l is bad") log.warning(la.norm(l_ - l[n].A)) return G
def restore_RCF_r(self): G_n_i = None for n in reversed(xrange(1, self.N + 2)): G_n_i, G_n = self.restore_ONR_n(n, G_n_i) self.r[n - 1] = mm.eyemat(self.D[n - 1], self.typ) if self.sanity_checks: r_n = mm.eyemat(self.D[n], self.typ) r_nm1 = self.eps_r(n, r_n) if not sp.allclose(r_nm1, self.r[n - 1].A, atol=1E-13, rtol=1E-13): print "Sanity Fail in restore_RCF_r!: r_%u is bad" % (n - 1) print la.norm(r_nm1 - self.r[n - 1]) #self.r[self.N + 1] = self.r[self.N] #Now G_n_i contains g_0_i for s in xrange(self.q[0]): #Note: This does not change the scale of A[0] self.A[0][s] = mm.mmul(G_n, self.A[0][s], G_n_i) self.u_gnd_l.r = mm.mmul(G_n, self.u_gnd_l.r, mm.H(G_n)) self.l[0] = mm.mmul(mm.H(G_n_i), self.l[0], G_n_i)
def _init_arrays(self): self.A = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 1..N self.r = sp.empty((self.N + 1), dtype=sp.ndarray) #Elements 0..N self.l = sp.empty((self.N + 1), dtype=sp.ndarray) self.r[0] = sp.zeros((self.D[0], self.D[0]), dtype=self.typ, order=self.odr) self.l[0] = m.eyemat(self.D[0], dtype=self.typ) for n in xrange(1, self.N + 1): self.r[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr) self.l[n] = sp.zeros((self.D[n], self.D[n]), dtype=self.typ, order=self.odr) self.A[n] = sp.zeros((self.q[n], self.D[n - 1], self.D[n]), dtype=self.typ, order=self.odr) sp.fill_diagonal(self.r[self.N], 1.)
def truncate(self, newD, update=True): assert newD < self.D, 'new bond-dimension must be smaller!' tmp_A = self.A tmp_l = self.l.diag self._init_arrays(newD, self.q) if self.symm_gauge: self.l = m.simple_diag_matrix(tmp_l[:self.D], dtype=self.typ) self.r = m.simple_diag_matrix(tmp_l[:self.D], dtype=self.typ) self.A = tmp_A[:, :self.D, :self.D] else: self.l = m.simple_diag_matrix(tmp_l[-self.D:], dtype=self.typ) self.r = m.eyemat(self.D, dtype=self.typ) self.A = tmp_A[:, -self.D:, -self.D:] self.l_before_CF = self.l.A self.r_before_CF = self.r.A if update: self.update()
def _restore_CF_diag(self, dbg=False): nc = self.N_centre #Want: r[0 <= n < nc] diagonal Ui = sp.eye(self.D[nc], dtype=self.typ) for n in xrange(nc, 0, -1): self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r( self.A[n], self.r[n], Ui, sanity_checks=self.sanity_checks) Ui = Um1_i #Now U is U_0 U = Um1 for s in xrange(self.q[0]): self.uni_l.A[0][s] = U.dot(self.uni_l.A[0][s]) self.uni_l.A[-1][s] = self.uni_l.A[-1][s].dot(Ui) self.uni_l.r[-1] = U.dot(self.uni_l.r[-1].dot(U.conj().T)) #And now: l[nc <= n <= N] diagonal if dbg: Um1 = sp.eye(self.D[nc - 1], dtype=self.typ) else: Um1 = mm.eyemat( self.D[nc - 1], dtype=self.typ ) #FIXME: This only works if l[nc - 1] is a special matrix type for n in xrange(nc, self.N + 1): self.l[n], U, Ui = tm.restore_RCF_l( self.A[n], self.l[n - 1], Um1, sanity_checks=self.sanity_checks) Um1 = U #Now, Um1 = U_N Um1_i = Ui for s in xrange(self.q[0]): self.uni_r.A[0][s] = Um1.dot(self.uni_r.A[0][s]) self.uni_r.A[-1][s] = self.uni_r.A[-1][s].dot(Um1_i) self.uni_r.l[-1] = Um1_i.conj().T.dot(self.uni_r.l[-1].dot(Um1_i))
def _restore_CF_diag(self): nc = self.N_centre self.S_hc = sp.zeros((self.N + 1), dtype=sp.complex128) #Want: r[0 <= n < nc] diagonal Ui = sp.eye(self.D[nc], dtype=self.typ) for n in xrange(nc, 0, -1): self.r[n - 1], Um1, Um1_i = tm.restore_LCF_r(self.A[n], self.r[n], Ui, sanity_checks=self.sanity_checks) self.S_hc[n - 1] = -sp.sum(self.r[n - 1].diag * sp.log2(self.r[n - 1].diag)) Ui = Um1_i #Now U is U_0 U = Um1 for s in xrange(self.q[0]): self.A[0][s] = U.dot(self.A[0][s]).dot(Ui) self.uni_l.r = U.dot(self.uni_l.r.dot(U.conj().T)) #And now: l[nc <= n <= N] diagonal Um1 = mm.eyemat(self.D[nc - 1], dtype=self.typ) for n in xrange(nc, self.N + 1): self.l[n], U, Ui = tm.restore_RCF_l(self.A[n], self.l[n - 1], Um1, sanity_checks=self.sanity_checks) self.S_hc[n] = -sp.sum(self.l[n].diag * sp.log2(self.l[n].diag)) Um1 = U #Now, Um1 = U_N Um1_i = Ui for s in xrange(self.q[0]): self.A[self.N + 1][s] = Um1.dot(self.A[self.N + 1][s]).dot(Um1_i) self.uni_r.l = Um1_i.conj().T.dot(self.uni_r.l.dot(Um1_i))
def restore_RCF(self, start=-1, update_l=True, normalize=True, diag_l=True): """Use a gauge-transformation to restore right canonical form. Implements the conditions for right canonical form from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. This performs two 'almost' gauge transformations, where the 'almost' means we allow the norm to vary (if "normalize" = True). The last step (A[1]) is done diffently to the others since G[0], the gauge-transf. matrix, is just a number, which can be found more efficiently and accurately without using matrix methods. The last step (A[1]) is important because, if we have successfully made r[1] = 1 in the previous steps, it fully determines the normalization of the state via r[0] ( = l[N]). Optionally (normalize=False), the function will not attempt to make A[1] satisfy the orthonorm. condition, and will take G[0] = 1 = G[N], thus performing a pure gauge-transformation, but not ensuring complete canonical form. It is also possible to begin the process from a site n other than N, in case the sites > n are known to be in the desired form already. It is also possible to skip the diagonalization of the l's, such that only the right orthonormalization condition (r_n = eye) is met. By default, the l's are updated even if diag_l=False. FIXME: Currently, "start" only affects the ON_R stage! Parameters ---------- start : int The rightmost site to start from (defaults to N) update_l : bool Whether to call calc_l() after completion (defaults to True) normalize : bool Whether to also attempt to enforce the condition for A[1], which normalizes the state. diag_l : bool Whether to put l in diagonal form (defaults to True) """ if start < 1: start = self.N G_n_i = sp.eye(self.D[start], dtype=self.typ) #This is actually just the number 1 for n in reversed(xrange(2, start + 1)): G_n_i = self.restore_ONR_n(n, G_n_i) self.eps_r(n, self.r[n], out=self.r[n - 1]) #Update r[n - 1], which should, ideally, now equal 1 #self.r[n - 1][:] = sp.eye(self.D[n - 1]) #self.r[n - 1] = m.eyemat(self.D[n - 1], dtype=self.typ) #print self.r[n - 1] if self.sanity_checks and not diag_l: r_nm1 = self.eps_r(n, m.eyemat(self.D[n], self.typ)) if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: r_%u is bad" % n #Now do A[1]... #Apply the remaining G[1]^-1 from the previous step. for s in xrange(self.q[1]): self.A[1][s] = m.mmul(self.A[1][s], G_n_i) #Now finish off self.eps_r(1, self.r[1], out=self.r[0]) if normalize: G0 = 1. / sp.sqrt(self.r[0].squeeze().real) self.A[1] *= G0 self.r[0][:] = 1 if self.sanity_checks: r0 = self.eps_r(1, self.r[1]) if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: r_0 is bad / norm failure" if diag_l: G_nm1 = sp.eye(self.D[0], dtype=self.typ) for n in xrange(1, self.N): x = m.mmul(m.H(G_nm1), self.l[n - 1], G_nm1) M = self.eps_l(n, x) ev, EV = la.eigh(M) G_n_i = EV self.l[n][:] = sp.diag(ev) #self.l[n] = m.simple_diag_matrix(sp.array(ev, dtype=self.typ)) for s in xrange(self.q[n]): self.A[n][s] = m.mmul(G_nm1, self.A[n][s], G_n_i) if self.sanity_checks: l = self.eps_l(n, self.l[n - 1]) if not sp.allclose(l, self.l[n]): print "Sanity Fail in restore_RCF!: l_%u is bad" % n G_nm1 = m.H(EV) #Apply remaining G_Nm1 to A[N] n = self.N for s in xrange(self.q[n]): self.A[n][s] = m.mmul(G_nm1, self.A[n][s]) #Deal with final, scalar l[N] self.eps_l(n, self.l[n - 1], out=self.l[n]) if self.sanity_checks: if not sp.allclose(self.l[self.N].real, 1, atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: l_N is bad / norm failure" print "l_N = " + str(self.l[self.N].squeeze().real) for n in xrange(1, self.N + 1): r_nm1 = self.eps_r(n, m.eyemat(self.D[n], self.typ)) if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: r_%u is bad" % n return True #FIXME: This OK? elif update_l: res = self.calc_l() return res else: return True
def restore_RCF_r(A, r, G_n_i, zero_tol=1E-15, sanity_checks=False, sc_data=''): """Transforms a single A[n] to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. This function must be called for each n in turn, starting at N + 1, passing the gauge transformation matrix from the previous step as an argument. Finds a G[n-1] such that orthonormalization is fulfilled for n. If rank-deficiency is encountered, the result fulfills the orthonormality condition in the occupied subspace with the zeros at the top-left (for example r = diag([0, 0, 1, 1, 1, 1, 1])). Parameters ---------- A : ndarray The parameter tensor for the nth site A[n]. r : ndarray or object with array interface The matrix r[n]. G_n_i : ndarray The inverse gauge transform matrix for site n obtained in the previous step (for n + 1). sanity_checks : bool (False) Whether to perform additional sanity checks. zero_tol : float Tolerance for detecting zeros. Returns ------- r_nm1 : ndarray or simple_diag_matrix or eyemat The new matrix r[n - 1]. G_nm1 : ndarray The gauge transformation matrix for the site n - 1. G_n_m1_i : ndarray The inverse gauge transformation matrix for the site n - 1. """ if G_n_i is None: GGh_n_i = r else: GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T)) M = eps_r_noop(GGh_n_i, A, A) X, Xi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, sanity_checks=sanity_checks) G_nm1 = Xi.conj().T G_nm1_i = X.conj().T if G_n_i is None: G_n_i = G_nm1_i if sanity_checks: #GiG may not be equal to eye in the case of rank-deficiency, #but the rest should lie in the null space of A. GiG = G_nm1_i.dot(G_nm1) As = np.sum(A, axis=0) if not sp.allclose( GiG.dot(As).dot(G_n_i), As.dot(G_n_i), atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s", la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)), sc_data) for s in xrange(A.shape[0]): A[s] = G_nm1.dot(A[s]).dot(G_n_i) if new_D == A.shape[1]: r_nm1 = mm.eyemat(A.shape[1], A.dtype) else: r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype) r_nm1[-new_D:] = 1 r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype) if sanity_checks: r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning( "Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) r_nm1_ = eps_r_noop(r, A, A) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) return r_nm1, G_nm1, G_nm1_i
def restore_RCF(self, dbg=False): if dbg: self.calc_l() self.calc_r() print "BEFORE..." h_before, h_left_before, h_right_before = self.restore_RCF_dbg() print (h_left_before, h_before, h_right_before) self.restore_RCF_r() if dbg: self.calc_l() print "MIDDLE..." h_mid, h_left_mid, h_right_mid = self.restore_RCF_dbg() print (h_left_mid, h_mid, h_right_mid) fac = 1 / self.l[0].trace().real if dbg: print "Scale l[0]: %g" % fac self.l[0] *= fac self.u_gnd_l.r *= 1/fac self.restore_RCF_l() if dbg: print "Uni left:" self.u_gnd_l.A = self.A[0] self.u_gnd_l.l = self.l[0] self.u_gnd_l.calc_lr() #Ensures largest ev of E=1 self.l[0] = self.u_gnd_l.l #No longer diagonal! self.A[0] = self.u_gnd_l.A if self.sanity_checks: if not sp.allclose(self.l[0], sp.diag(sp.diag(self.l[0])), atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: True l[0] not diagonal!" self.l[0] = mm.simple_diag_matrix(sp.diag(self.l[0])) fac = 1 / sp.trace(self.l[0]).real if dbg: print "Scale l[0]: %g" % fac self.l[0] *= fac self.u_gnd_l.r *= 1/fac self.u_gnd_l.l = self.l[0] if dbg: print "Uni right:" self.u_gnd_r.A = self.A[self.N + 1] self.u_gnd_r.r = self.r[self.N] self.u_gnd_r.calc_lr() #Ensures largest ev of E=1 self.r[self.N] = self.u_gnd_r.r self.A[self.N + 1] = self.u_gnd_r.A if self.sanity_checks: if not sp.allclose(self.r[self.N], sp.eye(self.D[self.N]), atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: True r[N] not eye!" self.r[self.N] = mm.eyemat(self.D[self.N], dtype=self.typ) self.u_gnd_r.r = self.r[self.N] self.r[self.N + 1] = self.r[self.N] self.l[self.N + 1][:] = self.eps_l(self.N + 1, self.l[self.N]) if self.sanity_checks: l_n = self.l[0] for n in xrange(0, self.N + 1): l_n = self.eps_l(n, l_n) if not sp.allclose(l_n, self.l[n], atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: l_%u is bad" % n r_nm1 = self.r[self.N + 1] for n in reversed(xrange(1, self.N + 2)): r_nm1 = self.eps_r(n, r_nm1) if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-12, rtol=1E-12): print "Sanity Fail in restore_RCF!: r_%u is bad" % (n - 1) if dbg: print "AFTER..." h_after, h_left_after, h_right_after = self.restore_RCF_dbg() print (h_left_after, h_after, h_right_after) print h_after - h_before print (h_after.sum() - h_before.sum() + h_left_after - h_left_before + h_right_after - h_right_before)
def restore_CF(self, ret_g=False): if self.symm_gauge: self.restore_SCF() else: #First get G such that r = eye G = la.cholesky(self.r, lower=True) G_i = m.invtr(G, lower=True) self.l = m.mmul(m.H(G), self.l, G) #Now bring l into diagonal form, trace = 1 (guaranteed by r = eye..?) ev, EV = la.eigh(self.l) G = G.dot(EV) G_i = m.H(EV).dot(G_i) for s in xrange(self.q): self.A[s] = m.mmul(G_i, self.A[s], G) #ev contains the squares of the Schmidt coefficients, self.S_hc = - np.sum(ev * sp.log2(ev)) self.l = m.simple_diag_matrix(ev, dtype=self.typ) if self.sanity_checks: M = np.zeros_like(self.r) for s in xrange(self.q): M += m.mmul(self.A[s], m.H(self.A[s])) self.r = m.mmul(G_i, self.r, m.H(G_i)) if not np.allclose(M, self.r, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): print "Sanity check failed: RestoreRCF, bad M." print "Off by: " + str(la.norm(M - self.r)) if not np.allclose(self.r, np.eye(self.D), rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): print "Sanity check failed: r not identity." print "Off by: " + str(la.norm(np.eye(self.D) - self.r)) l = self.eps_l(self.l) r = self.eps_r(self.r) if not np.allclose(r, self.r, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): print "Sanity check failed: Restore_RCF, bad r!" print "Off by: " + str(la.norm(r - self.r)) if not np.allclose(l, self.l, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): print "Sanity check failed: Restore_RCF, bad l!" print "Off by: " + str(la.norm(l - self.l)) self.r = m.eyemat(self.D, dtype=self.typ) if ret_g: return G, G_i else: return
def calc_BHB(self, x, p, tdvp, tdvp2, prereq, M_prev=None, y_pi_prev=None, pinv_solver=None): if pinv_solver is None: pinv_solver = las.gmres if self.ham_sites == 3: V_, Vr_, Vri_, Vri_A_, C_, C_Vri_AA_, C_AAA_r_Ah_Vrih, \ C_AhAhlAA, C_AA_r_Ah_Vrih_, C_AAA_Vrh_, C_Vri_A_r_Ah_, \ C_AhlAA, C_AhlAA_conj, C_AA_Vrh, rhs10 = prereq else: C_, C_conj, V_, Vr_, Vri_, C_Vri_A_conj, C_AhlA, C_A_Vrh_, rhs10 = prereq A = tdvp.A[0] A_ = tdvp2.A[0] AA = tdvp.AA[0] l = tdvp.l[0] r_ = tdvp2.r[0] l_sqrt = tdvp.l_sqrt[0] l_sqrt_i = tdvp.l_sqrt_i[0] r__sqrt = tdvp2.r_sqrt[0] r__sqrt_i = tdvp2.r_sqrt_i[0] K__r = tdvp2.K[0] K_l = tdvp.K_left[0] pseudo = tdvp2 is tdvp B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i) #Skip zeros due to rank-deficiency if la.norm(B) == 0: return sp.zeros_like(x), M_prev, y_pi_prev if self.sanity_checks: tst = tm.eps_r_noop(r_, B, A_) if not la.norm(tst) > self.sanity_tol: log.warning("Sanity check failed: Gauge-fixing violation! " + str(la.norm(tst))) if self.sanity_checks: B2 = np.zeros_like(B) for s in xrange(self.q): B2[s] = l_sqrt_i.dot(x.dot(Vri_[s])) if la.norm(B - B2) / la.norm(B) > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad Vri!") BA_ = tm.calc_AA(B, A_) AB = tm.calc_AA(A, B) if self.ham_sites == 3: BAA_ = tm.calc_AAA_AA(BA_, A_) ABA_ = tm.calc_AAA_AA(AB, A_) AAB = tm.calc_AAA_AA(AA, B) y = tm.eps_l_noop(l, B, A) # if pseudo: # y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing M = pinv_1mE(y, [A_], [A], l, r_, p=-p, left=True, pseudo=pseudo, out=M_prev, tol=self.pinv_tol, solver=pinv_solver, use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch, sanity_checks=self.sanity_checks, sc_data='M') #print m.adot(r, M) if self.sanity_checks: y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A) norm = la.norm(y.ravel()) if norm == 0: norm = 1 tst = la.norm(y - y2) / norm if tst > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst) # if pseudo: # M = M - l * m.adot(r_, M) Mh = M.conj().T.copy(order='C') if self.ham_sites == 3: tmp = BAA_ + sp.exp(+1.j * p) * ABA_ + sp.exp(+2.j * p) * AAB res = l_sqrt.dot(tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_Vri_AA_)) #1 1D, #3, #3c else: tmp = BA_ + sp.exp(+1.j * p) * AB res = l_sqrt.dot(tm.eps_r_op_2s_AA12_C34(r_, tmp, C_Vri_A_conj)) #1, #3 OK res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(rhs10)) #10 exp = sp.exp subres = sp.zeros_like(res) eye = m.eyemat(C_.shape[2], dtype=tdvp.typ) eye2 = m.eyemat(A.shape[2], dtype=tdvp.typ) if self.ham_sites == 3: subres += exp(-2.j * p) * tm.eps_l_noop(Mh, A, C_AAA_r_Ah_Vrih) #12 subres += exp(-3.j * p) * tm.eps_l_op_2s_AA12_C34(Mh, AA, C_AAA_Vrh_) #12b for s in xrange(self.q): #subres += exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_AAA_r_Ah_Vrih[s])) #12 subres += tm.eps_r_noop(B[s], C_AhAhlAA[s, :], Vr_) #2b subres += exp(-1.j * p) * tm.eps_l_noop(l.dot(B[s]), A, C_AA_r_Ah_Vrih_[s, :]) #4 subres += A[s].conj().T.dot(l.dot(tm.eps_r_op_2s_AA12_C34(eye2, AB, C_Vri_A_r_Ah_[s, :, :]))) #2 -ive of that it should be.... subres += exp(-1.j * p) * tm.eps_l_op_2s_AA12_C34(eye2, C_AhlAA_conj[s, :, :], BA_).dot(Vr_[s].conj().T) #4b subres += exp(-2.j * p) * tm.eps_l_op_2s_AA12_C34(l.dot(B[s]), AA, C_AA_Vrh[s, :, :]) #4c subres += exp(+1.j * p) * tm.eps_r_op_2s_AA12_C34(r_.dot_left(B[s]), C_AhlAA[s, :, :], Vri_A_) #3b #for t in xrange(self.q): #subres += (C_AhAhlAA[t, s].dot(B[s]).dot(Vr_[t].conj().T)) #2b #subres += (exp(-1.j * p) * A[s].conj().T.dot(l.dot(B[t])).dot(C_AA_r_Ah_Vrih_[s, t])) #4 #subres += (exp(-3.j * p) * AA[t, s].conj().T.dot(Mh).dot(C_AAA_Vrh_[t, s])) #12b #for u in xrange(self.q): #subres += A[s].conj().T.dot(l.dot(AB[t, u]).dot(C_A_r_Ah_Vrih[s, t, u])) #2 -ive of that it should be.... #subres += (exp(+1.j * p) * C_AhlAA[t, s, s].dot(B[u]).dot(r_.dot(A_[u].conj().T)).dot(Vri_[t].conj().T)) #3b #subres += (exp(-1.j * p) * C_AhAhlA[s, t, u].dot(BA_[t, u]).dot(Vr_[s].conj().T)) #4b #subres += (exp(-2.j * p) * AA[t, s].conj().T.dot(l.dot(B[u])).dot(C_AA_Vrh[t, s, u])) #4c else: for s in xrange(self.q): #subres += C_AhlA[s, t].dot(B[s]).dot(Vr_[t].conj().T) #2 OK subres += tm.eps_r_noop(B[s], C_AhlA[s, :], Vr_) #2 #+ exp(-1.j * p) * A[t].conj().T.dot(l.dot(B[s])).dot(C_A_Vrh_[t, s]) #4 OK with 3 subres += exp(-1.j * p) * tm.eps_l_noop(l.dot(B[s]), A, C_A_Vrh_[s, :]) #4 #+ exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_[s, t])).dot(Vr_[t].conj().T)) #12 subres += exp(-2.j * p) * A[s].conj().T.dot(Mh).dot(tm.eps_r_noop(eye, C_[s, :], Vr_)) #12 res += l_sqrt_i.dot(subres) res += l_sqrt.dot(tm.eps_r_noop(K__r, B, Vri_)) #5 res += l_sqrt_i.dot(K_l.dot(tm.eps_r_noop(r__sqrt, B, V_))) #6 res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(tm.eps_r_noop(K__r, A_, Vri_))) #8 y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_) #7 if self.ham_sites == 3: tmp = sp.exp(+1.j * p) * BAA_ + sp.exp(+2.j * p) * ABA_ + sp.exp(+3.j * p) * AAB #9, #11, #11b y = y1 + tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_) elif self.ham_sites == 2: tmp = sp.exp(+1.j * p) * BA_ + sp.exp(+2.j * p) * AB #9, #11 y = y1 + tm.eps_r_op_2s_AA12_C34(r_, tmp, C_conj) if pseudo: y = y - m.adot(l, y) * r_ y_pi = pinv_1mE(y, [A], [A_], l, r_, p=p, left=False, pseudo=pseudo, out=y_pi_prev, tol=self.pinv_tol, solver=pinv_solver, use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch, sanity_checks=self.sanity_checks, sc_data='y_pi') #print m.adot(l, y_pi) if self.sanity_checks: z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_) tst = la.norm((y - z).ravel()) / la.norm(y.ravel()) if tst > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g", tst) res += l_sqrt.dot(tm.eps_r_noop(y_pi, A, Vri_)) if self.sanity_checks: expval = m.adot(x, res) / m.adot(x, x) #print "expval = " + str(expval) if expval < -self.sanity_tol: log.warning("Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)", expval) if abs(expval.imag) > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)", expval) return res, M, y_pi
def restore_RCF(self, ret_g=False, zero_tol=None): """Restores right canonical form. In this form, self.r = sp.eye(self.D) and self.l is diagonal, with the squared Schmidt coefficients corresponding to the half-chain decomposition as eigenvalues. Parameters ---------- ret_g : bool Whether to return the gauge-transformation matrices used. Returns ------- g, g_i : ndarray Gauge transformation matrix g and its inverse g_i. """ if zero_tol is None: zero_tol = self.zero_tol #First get G such that r = eye G, G_i, rank = tm.herm_fac_with_inv(self.r, lower=True, zero_tol=zero_tol, return_rank=True) self.l = m.mmul(m.H(G), self.l, G) #Now bring l into diagonal form, trace = 1 (guaranteed by r = eye..?) ev, EV = la.eigh(self.l) G = G.dot(EV) G_i = m.H(EV).dot(G_i) for s in xrange(self.q): self.A[s] = m.mmul(G_i, self.A[s], G) #ev contains the squares of the Schmidt coefficients, self.S_hc = - np.sum(ev * sp.log2(ev)) self.l = m.simple_diag_matrix(ev, dtype=self.typ) r_old = self.r if rank == self.D: self.r = m.eyemat(self.D, self.typ) else: self.r = sp.zeros((self.D), dtype=self.typ) self.r[-rank:] = 1 self.r = m.simple_diag_matrix(self.r, dtype=self.typ) if self.sanity_checks: r_ = m.mmul(G_i, r_old, m.H(G_i)) if not np.allclose(self.r, r_, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): log.warning("Sanity check failed: RestoreRCF, bad r (bad GT).") l = tm.eps_l_noop(self.l, self.A, self.A) r = tm.eps_r_noop(self.r, self.A, self.A) if not np.allclose(r, self.r, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): log.warning("Sanity check failed: Restore_RCF, r not eigenvector! %s", la.norm(r - self.r)) if not np.allclose(l, self.l, rtol=self.itr_rtol*self.check_fac, atol=self.itr_atol*self.check_fac): log.warning("Sanity check failed: Restore_RCF, l not eigenvector! %s", la.norm(l - self.l)) if ret_g: return G, G_i else: return
def restore_RCF_r(A, r, G_n_i, zero_tol=1E-15, sanity_checks=False, sc_data=''): """Transforms a single A[n] to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. This function must be called for each n in turn, starting at N + 1, passing the gauge transformation matrix from the previous step as an argument. Finds a G[n-1] such that orthonormalization is fulfilled for n. If rank-deficiency is encountered, the result fulfills the orthonormality condition in the occupied subspace with the zeros at the top-left (for example r = diag([0, 0, 1, 1, 1, 1, 1])). Parameters ---------- A : ndarray The parameter tensor for the nth site A[n]. r : ndarray or object with array interface The matrix r[n]. G_n_i : ndarray The inverse gauge transform matrix for site n obtained in the previous step (for n + 1). sanity_checks : bool (False) Whether to perform additional sanity checks. zero_tol : float Tolerance for detecting zeros. Returns ------- r_nm1 : ndarray or simple_diag_matrix or eyemat The new matrix r[n - 1]. G_nm1 : ndarray The gauge transformation matrix for the site n - 1. G_n_m1_i : ndarray The inverse gauge transformation matrix for the site n - 1. """ if G_n_i is None: GGh_n_i = r else: GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T)) M = eps_r_noop(GGh_n_i, A, A) X, Xi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, sanity_checks=sanity_checks) G_nm1 = Xi.conj().T G_nm1_i = X.conj().T if G_n_i is None: G_n_i = G_nm1_i if sanity_checks: #GiG may not be equal to eye in the case of rank-deficiency, #but the rest should lie in the null space of A. GiG = G_nm1_i.dot(G_nm1) As = np.sum(A, axis=0) if not sp.allclose(GiG.dot(As).dot(G_n_i), As.dot(G_n_i), atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s", la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)), sc_data) for s in xrange(A.shape[0]): A[s] = G_nm1.dot(A[s]).dot(G_n_i) if new_D == A.shape[1]: r_nm1 = mm.eyemat(A.shape[1], A.dtype) else: r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype) r_nm1[-new_D:] = 1 r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype) if sanity_checks: r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) r_nm1_ = eps_r_noop(r, A, A) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) return r_nm1, G_nm1, G_nm1_i
def calc_BHB(self, x, p, tdvp, tdvp2, prereq, M_prev=None, y_pi_prev=None, pinv_solver=None): if pinv_solver is None: pinv_solver = las.gmres if self.ham_sites == 3: V_, Vr_, Vri_, Vri_A_, C_, C_Vri_AA_, C_AAA_r_Ah_Vrih, \ C_AhAhlAA, C_AA_r_Ah_Vrih_, C_AAA_Vrh_, C_Vri_A_r_Ah_, \ C_AhlAA, C_AhlAA_conj, C_AA_Vrh, rhs10 = prereq else: C_, C_conj, V_, Vr_, Vri_, C_Vri_A_conj, C_AhlA, C_A_Vrh_, rhs10 = prereq A = tdvp.A[0] A_ = tdvp2.A[0] AA = tdvp.AA[0] l = tdvp.l[0] r_ = tdvp2.r[0] l_sqrt = tdvp.l_sqrt[0] l_sqrt_i = tdvp.l_sqrt_i[0] r__sqrt = tdvp2.r_sqrt[0] r__sqrt_i = tdvp2.r_sqrt_i[0] K__r = tdvp2.K[0] K_l = tdvp.K_left[0] pseudo = tdvp2 is tdvp B = tdvp2.get_B_from_x(x, tdvp2.Vsh[0], l_sqrt_i, r__sqrt_i) #Skip zeros due to rank-deficiency if la.norm(B) == 0: return sp.zeros_like(x), M_prev, y_pi_prev if self.sanity_checks: tst = tm.eps_r_noop(r_, B, A_) if not la.norm(tst) > self.sanity_tol: log.warning("Sanity check failed: Gauge-fixing violation! " + str(la.norm(tst))) if self.sanity_checks: B2 = np.zeros_like(B) for s in xrange(self.q): B2[s] = l_sqrt_i.dot(x.dot(Vri_[s])) if la.norm(B - B2) / la.norm(B) > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad Vri!") BA_ = tm.calc_AA(B, A_) AB = tm.calc_AA(A, B) if self.ham_sites == 3: BAA_ = tm.calc_AAA_AA(BA_, A_) ABA_ = tm.calc_AAA_AA(AB, A_) AAB = tm.calc_AAA_AA(AA, B) y = tm.eps_l_noop(l, B, A) # if pseudo: # y = y - m.adot(r_, y) * l #should just = y due to gauge-fixing M = pinv_1mE(y, [A_], [A], l, r_, p=-p, left=True, pseudo=pseudo, out=M_prev, tol=self.pinv_tol, solver=pinv_solver, use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch, sanity_checks=self.sanity_checks, sc_data='M') #print m.adot(r, M) if self.sanity_checks: y2 = M - sp.exp(+1.j * p) * tm.eps_l_noop(M, A_, A) norm = la.norm(y.ravel()) if norm == 0: norm = 1 tst = la.norm(y - y2) / norm if tst > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad M. Off by: %g", tst) # if pseudo: # M = M - l * m.adot(r_, M) Mh = M.conj().T.copy(order='C') if self.ham_sites == 3: tmp = BAA_ + sp.exp(+1.j * p) * ABA_ + sp.exp(+2.j * p) * AAB res = l_sqrt.dot(tm.eps_r_op_3s_C123_AAA456( r_, tmp, C_Vri_AA_)) #1 1D, #3, #3c else: tmp = BA_ + sp.exp(+1.j * p) * AB res = l_sqrt.dot(tm.eps_r_op_2s_AA12_C34(r_, tmp, C_Vri_A_conj)) #1, #3 OK res += sp.exp(-1.j * p) * l_sqrt_i.dot(Mh.dot(rhs10)) #10 exp = sp.exp subres = sp.zeros_like(res) eye = m.eyemat(C_.shape[2], dtype=tdvp.typ) eye2 = m.eyemat(A.shape[2], dtype=tdvp.typ) if self.ham_sites == 3: subres += exp(-2.j * p) * tm.eps_l_noop(Mh, A, C_AAA_r_Ah_Vrih) #12 subres += exp(-3.j * p) * tm.eps_l_op_2s_AA12_C34( Mh, AA, C_AAA_Vrh_) #12b for s in xrange(self.q): #subres += exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_AAA_r_Ah_Vrih[s])) #12 subres += tm.eps_r_noop(B[s], C_AhAhlAA[s, :], Vr_) #2b subres += exp(-1.j * p) * tm.eps_l_noop( l.dot(B[s]), A, C_AA_r_Ah_Vrih_[s, :]) #4 subres += A[s].conj().T.dot( l.dot( tm.eps_r_op_2s_AA12_C34(eye2, AB, C_Vri_A_r_Ah_[ s, :, :]))) #2 -ive of that it should be.... subres += exp(-1.j * p) * tm.eps_l_op_2s_AA12_C34( eye2, C_AhlAA_conj[s, :, :], BA_).dot(Vr_[s].conj().T) #4b subres += exp(-2.j * p) * tm.eps_l_op_2s_AA12_C34( l.dot(B[s]), AA, C_AA_Vrh[s, :, :]) #4c subres += exp(+1.j * p) * tm.eps_r_op_2s_AA12_C34( r_.dot_left(B[s]), C_AhlAA[s, :, :], Vri_A_) #3b #for t in xrange(self.q): #subres += (C_AhAhlAA[t, s].dot(B[s]).dot(Vr_[t].conj().T)) #2b #subres += (exp(-1.j * p) * A[s].conj().T.dot(l.dot(B[t])).dot(C_AA_r_Ah_Vrih_[s, t])) #4 #subres += (exp(-3.j * p) * AA[t, s].conj().T.dot(Mh).dot(C_AAA_Vrh_[t, s])) #12b #for u in xrange(self.q): #subres += A[s].conj().T.dot(l.dot(AB[t, u]).dot(C_A_r_Ah_Vrih[s, t, u])) #2 -ive of that it should be.... #subres += (exp(+1.j * p) * C_AhlAA[t, s, s].dot(B[u]).dot(r_.dot(A_[u].conj().T)).dot(Vri_[t].conj().T)) #3b #subres += (exp(-1.j * p) * C_AhAhlA[s, t, u].dot(BA_[t, u]).dot(Vr_[s].conj().T)) #4b #subres += (exp(-2.j * p) * AA[t, s].conj().T.dot(l.dot(B[u])).dot(C_AA_Vrh[t, s, u])) #4c else: for s in xrange(self.q): #subres += C_AhlA[s, t].dot(B[s]).dot(Vr_[t].conj().T) #2 OK subres += tm.eps_r_noop(B[s], C_AhlA[s, :], Vr_) #2 #+ exp(-1.j * p) * A[t].conj().T.dot(l.dot(B[s])).dot(C_A_Vrh_[t, s]) #4 OK with 3 subres += exp(-1.j * p) * tm.eps_l_noop( l.dot(B[s]), A, C_A_Vrh_[s, :]) #4 #+ exp(-2.j * p) * A[s].conj().T.dot(Mh.dot(C_[s, t])).dot(Vr_[t].conj().T)) #12 subres += exp(-2.j * p) * A[s].conj().T.dot(Mh).dot( tm.eps_r_noop(eye, C_[s, :], Vr_)) #12 res += l_sqrt_i.dot(subres) res += l_sqrt.dot(tm.eps_r_noop(K__r, B, Vri_)) #5 res += l_sqrt_i.dot(K_l.dot(tm.eps_r_noop(r__sqrt, B, V_))) #6 res += sp.exp(-1.j * p) * l_sqrt_i.dot( Mh.dot(tm.eps_r_noop(K__r, A_, Vri_))) #8 y1 = sp.exp(+1.j * p) * tm.eps_r_noop(K__r, B, A_) #7 if self.ham_sites == 3: tmp = sp.exp(+1.j * p) * BAA_ + sp.exp(+2.j * p) * ABA_ + sp.exp( +3.j * p) * AAB #9, #11, #11b y = y1 + tm.eps_r_op_3s_C123_AAA456(r_, tmp, C_) elif self.ham_sites == 2: tmp = sp.exp(+1.j * p) * BA_ + sp.exp(+2.j * p) * AB #9, #11 y = y1 + tm.eps_r_op_2s_AA12_C34(r_, tmp, C_conj) if pseudo: y = y - m.adot(l, y) * r_ y_pi = pinv_1mE(y, [A], [A_], l, r_, p=p, left=False, pseudo=pseudo, out=y_pi_prev, tol=self.pinv_tol, solver=pinv_solver, use_CUDA=self.pinv_CUDA, CUDA_use_batch=self.pinv_CUDA_batch, sanity_checks=self.sanity_checks, sc_data='y_pi') #print m.adot(l, y_pi) if self.sanity_checks: z = y_pi - sp.exp(+1.j * p) * tm.eps_r_noop(y_pi, A, A_) tst = la.norm((y - z).ravel()) / la.norm(y.ravel()) if tst > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! Bad x_pi. Off by: %g", tst) res += l_sqrt.dot(tm.eps_r_noop(y_pi, A, Vri_)) if self.sanity_checks: expval = m.adot(x, res) / m.adot(x, x) #print "expval = " + str(expval) if expval < -self.sanity_tol: log.warning( "Sanity Fail in calc_BHB! H is not pos. semi-definite (%s)", expval) if abs(expval.imag) > self.sanity_tol: log.warning("Sanity Fail in calc_BHB! H is not Hermitian (%s)", expval) return res, M, y_pi