def expect_1s(self, op, n): """Computes the expectation value of a single-site operator. The operator should be a q[n] x q[n] matrix or generating function such that op[s, t] or op(s, t) equals <s|op|t>. The state must be up-to-date -- see self.update()! Parameters ---------- op : ndarray or callable The operator. n : int The site number (1 <= n <= N). Returns ------- expval : floating point number The expectation value (data type may be complex) """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) res = tm.eps_r_op_1s(self.r[n], self.A[n], self.A[n], op) return m.adot(self.l[n - 1], res)
def expect_1s(self, op): """Computes the expectation value of a single-site operator. The operator should be a self.q x self.q matrix or generating function such that op[s, t] or op(s, t) equals <s|op|t>. The state must be up-to-date -- see self.update()! Parameters ---------- op : ndarray or callable The operator. Returns ------- expval : floating point number The expectation value (data type may be complex) """ if callable(op): op = np.vectorize(op, otypes=[np.complex128]) op = np.fromfunction(op, (self.q, self.q)) Or = tm.eps_r_op_1s(self.r, self.A, self.A, op) return m.adot(self.l, Or)
def expect_1s_1s(self, op1, op2, d): """Computes the expectation value of two single site operators acting on two different sites. The result is < op1_n op2_n+d > with the operators acting on sites n and n + d. See expect_1s(). Requires d > 0. The state must be up-to-date -- see self.update()! Parameters ---------- op1 : ndarray or callable The first operator, acting on the first site. op2 : ndarray or callable The second operator, acting on the second site. d : int The distance (number of sites) between the two sites acted on non-trivially. Returns ------- expval : floating point number The expectation value (data type may be complex) """ assert d > 0, 'd must be greater than 1' if callable(op1): op1 = sp.vectorize(op1, otypes=[sp.complex128]) op1 = sp.fromfunction(op1, (self.q, self.q)) if callable(op2): op2 = sp.vectorize(op2, otypes=[sp.complex128]) op2 = sp.fromfunction(op2, (self.q, self.q)) r_n = tm.eps_r_op_1s(self.r, self.A, self.A, op2) for n in xrange(d - 1): r_n = tm.eps_r_noop(r_n, self.A, self.A) r_n = tm.eps_r_op_1s(r_n, self.A, self.A, op1) return m.adot(self.l, r_n)
def calc_BHB_prereq(self, tdvp, tdvp2): """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors. This is called (indirectly) by the self.excite.. functions. Parameters ---------- tdvp2: EvoMPS_TDVP_Uniform Second state (may be the same, or another ground state). Returns ------- A lot of stuff. """ l = tdvp.l[0] r_ = tdvp2.r[0] r__sqrt = tdvp2.r_sqrt[0] r__sqrt_i = tdvp2.r_sqrt_i[0] A = tdvp.A[0] A_ = tdvp2.A[0] #Note: V has ~ D**2 * q**2 elements. We avoid making any copies of it except this one. # This one is only needed because low-level routines force V_[s] to be contiguous. # TODO: Store V instead of Vsh in tdvp_uniform too... V_ = sp.transpose(tdvp2.Vsh[0], axes=(0, 2, 1)).conj().copy(order='C') if self.ham_sites == 2: #eyeham = m.eyemat(self.q, dtype=sp.complex128) eyeham = sp.eye(self.q, dtype=sp.complex128) #diham = m.simple_diag_matrix(sp.repeat([-tdvp.h_expect.real], self.q)) diham = -tdvp.h_expect.real * sp.eye(self.q, dtype=sp.complex128) _ham_tp = self.ham_tp + [[diham, eyeham]] #subtract norm dof Ao1 = get_Aop(A, _ham_tp, 2, conj=False) AhlAo1 = [tm.eps_l_op_1s(l, A, A, o1.conj().T) for o1, o2 in _ham_tp] A_o2c = get_Aop(A_, _ham_tp, 1, conj=True) Ao1c = get_Aop(A, _ham_tp, 0, conj=True) A_Vr_ho2 = [tm.eps_r_op_1s(r__sqrt, A_, V_, o2) for o1, o2 in _ham_tp] A_A_o12c = get_A_ops(A_, A_, _ham_tp, conj=True) A_o1 = get_Aop(A_, _ham_tp, 2, conj=False) tmp = sp.empty((A_.shape[1], V_.shape[1]), dtype=A.dtype, order='C') tmp2 = sp.empty((A_.shape[1], A_o2c[0].shape[1]), dtype=A.dtype, order='C') rhs10 = 0 for al in xrange(len(A_o1)): tmp2 = tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2) tmp3 = m.mmul(tmp2, r__sqrt_i) rhs10 += tm.eps_r_noop_inplace(tmp3, A_o1[al], V_, tmp) return V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp elif self.ham_sites == 3: return
def expect_1s_1s(self, op1, op2, n1, n2): """Computes the expectation value of two single site operators acting on two different sites. The result is < op1 op2 >. See expect_1s(). Requires n1 < n2. The state must be up-to-date -- see self.update()! Parameters ---------- op1 : ndarray or callable The first operator, acting on the first site. op2 : ndarray or callable The second operator, acting on the second site. n1 : int The site number of the first site. n2 : int The site number of the second site (must be > n1). Returns ------- expval : floating point number The expectation value (data type may be complex) """ if callable(op1): op1 = sp.vectorize(op1, otypes=[sp.complex128]) op1 = sp.fromfunction(op1, (self.q[n1], self.q[n1])) if callable(op2): op2 = sp.vectorize(op2, otypes=[sp.complex128]) op2 = sp.fromfunction(op2, (self.q[n2], self.q[n2])) r_n = tm.eps_r_op_1s(self.r[n2], self.A[n2], self.A[n2], op2) for n in reversed(xrange(n1 + 1, n2)): r_n = tm.eps_r_noop(r_n, self.A[n], self.A[n]) r_n = tm.eps_r_op_1s(r_n, self.A[n1], self.A[n1], op1) return m.adot(self.l[n1 - 1], r_n)
def expect_1s_cor(self, op1, op2, n1, n2): """Computes the correlation of two single site operators acting on two different sites. See expect_1S(). n1 must be smaller than n2. Assumes that the state is normalized. Parameters ---------- op1 : function The first operator, acting on the first site. op2 : function The second operator, acting on the second site. n1 : int The site number of the first site. n2 : int The site number of the second site (must be > n1). """ A1 = self.get_A(n1) A2 = self.get_A(n2) if callable(op1): op1 = sp.vectorize(op1, otypes=[sp.complex128]) op1 = sp.fromfunction(op1, (A1.shape[0], A1.shape[0])) if callable(op2): op2 = sp.vectorize(op2, otypes=[sp.complex128]) op2 = sp.fromfunction(op2, (A2.shape[0], A2.shape[0])) r_n = tm.eps_r_op_1s(self.get_r(n2), A2, A2, op2) for n in reversed(xrange(n1 + 1, n2)): r_n = tm.eps_r_noop(r_n, self.get_A(n), self.get_A(n)) r_n = tm.eps_r_op_1s(r_n, A1, A1, op1) return mm.adot(self.get_l(n1 - 1), r_n)
def expect_1s(self, op, n): """Computes the expectation value of a single-site operator. A single-site operator is represented as a function taking three integer arguments (n, s, t) where n is the site number and s, t range from 0 to q[n] - 1 and define the requested matrix element <s|o|t>. Assumes that the state is normalized. Parameters ---------- o : ndarray or callable The operator. n : int The site number. """ A = self.get_A(n) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], A.shape[0])) res = tm.eps_r_op_1s(self.get_r(n), A, A, op) return mm.adot(self.get_l(n - 1), res)
def _excite_correlation_1s_1s(AL, AR, B, lL, rR, op1, op2, d, g): pseudo = AL is AR BBL = pinv_1mE(tm.eps_l_noop(lL, B, B), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) B1L = pinv_1mE(tm.eps_l_noop(lL, B, AL), [AR], [AL], lL, rR, p=0, left=True, pseudo=pseudo) B2L = pinv_1mE(tm.eps_l_noop(lL, AL, B), [AL], [AR], lL, rR, p=0, left=True, pseudo=pseudo) B1B2L = pinv_1mE(tm.eps_l_noop(B1L, AR, B), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) B2B1L = pinv_1mE(tm.eps_l_noop(B2L, B, AR), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) BBR = pinv_1mE(tm.eps_r_noop(rR, B, B), [AL], [AL], lL, rR, p=0, left=False, pseudo=True) print "gauge fixing:", la.norm(tm.eps_r_noop(rR, B, AR)) res = [0.] * (d + 1) #B's on the left terms (0, 1, 2, 5) res[0] += m.adot(tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR) res[0] += m.adot(tm.eps_l_op_1s(B1L, AR, B, op1.dot(op2)), rR) res[0] += m.adot(tm.eps_l_op_1s(B2L, B, AR, op1.dot(op2)), rR) res[0] += m.adot(tm.eps_l_op_1s(lL, B, B, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR) l1 = tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1) l1 += tm.eps_l_op_1s(B1L, AR, B, op1) l1 += tm.eps_l_op_1s(B2L, B, AR, op1) l1 += tm.eps_l_op_1s(lL, B, B, op1) for n in xrange(1, d + 1): res[n] += m.adot(l1, tm.eps_r_op_1s(rR, AR, AR, op2)) res[n] -= 2 * g[n] if n == d: break l1 = tm.eps_l_noop(l1, AR, AR) print 1, res #Terms 3, 4, 6, 7, a ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(B1L, AR, AL, op1) + tm.eps_l_op_1s(lL, B, AL, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AR, AL) rs = [None] * (d + 1) rs[d - 1] = tm.eps_r_op_1s(rR, AR, AR, op2) for k in xrange(d - 1, 0, -1): rs[k - 1] = tm.eps_r_noop(rs[k], AR, AR) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], AR, B)) res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, AR, B, op2)) print 2, res #Terms 3, 4, 6, 7, b ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(B2L, AL, AR, op1) + tm.eps_l_op_1s(lL, AL, B, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AL, AR) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, AR)) res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, B, AR, op2)) print 3, res #Term 8 ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(lL, AL, AL, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AL, AL) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, B)) res[n] -= g[n] print 4, res #Terms 9 and 10 for n in xrange(2, d + 1): for k in xrange(2, n): lj = tm.eps_l_noop(ls[k - 1], AL, B) for j in xrange(k + 1, n): res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], B, AR)) lj = tm.eps_l_noop(lj, AL, AR) res[n] += m.adot(lj, tm.eps_r_op_1s(rR, B, AR, op2)) lj = tm.eps_l_noop(ls[k - 1], B, AL) for j in xrange(k + 1, n): res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], AR, B)) lj = tm.eps_l_noop(lj, AL, AR) res[n] += m.adot(lj, tm.eps_r_op_1s(rR, AR, B, op2)) print 5, res #Term 11 res[0] += m.adot(tm.eps_l_op_1s(lL, AL, AL, op1.dot(op2) - g[0] * sp.eye(len(op1))), BBR) for n in xrange(1, d + 1): res[n] += m.adot(tm.eps_l_op_1s(ls[n - 1], AL, AL, op2), BBR) res[n] -= g[n] return res
def _excite_correlation_1s_1s(AL, AR, B, lL, rR, op1, op2, d, g): pseudo = AL is AR BBL = pinv_1mE(tm.eps_l_noop(lL, B, B), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) B1L = pinv_1mE(tm.eps_l_noop(lL, B, AL), [AR], [AL], lL, rR, p=0, left=True, pseudo=pseudo) B2L = pinv_1mE(tm.eps_l_noop(lL, AL, B), [AL], [AR], lL, rR, p=0, left=True, pseudo=pseudo) B1B2L = pinv_1mE(tm.eps_l_noop(B1L, AR, B), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) B2B1L = pinv_1mE(tm.eps_l_noop(B2L, B, AR), [AR], [AR], lL, rR, p=0, left=True, pseudo=True) BBR = pinv_1mE(tm.eps_r_noop(rR, B, B), [AL], [AL], lL, rR, p=0, left=False, pseudo=True) print "gauge fixing:", la.norm(tm.eps_r_noop(rR, B, AR)) res = [0.] * (d + 1) #B's on the left terms (0, 1, 2, 5) res[0] += m.adot( tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR) res[0] += m.adot(tm.eps_l_op_1s(B1L, AR, B, op1.dot(op2)), rR) res[0] += m.adot(tm.eps_l_op_1s(B2L, B, AR, op1.dot(op2)), rR) res[0] += m.adot( tm.eps_l_op_1s(lL, B, B, op1.dot(op2) - g[0] * sp.eye(len(op1))), rR) l1 = tm.eps_l_op_1s(BBL + B1B2L + B2B1L, AR, AR, op1) l1 += tm.eps_l_op_1s(B1L, AR, B, op1) l1 += tm.eps_l_op_1s(B2L, B, AR, op1) l1 += tm.eps_l_op_1s(lL, B, B, op1) for n in xrange(1, d + 1): res[n] += m.adot(l1, tm.eps_r_op_1s(rR, AR, AR, op2)) res[n] -= 2 * g[n] if n == d: break l1 = tm.eps_l_noop(l1, AR, AR) print 1, res #Terms 3, 4, 6, 7, a ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(B1L, AR, AL, op1) + tm.eps_l_op_1s(lL, B, AL, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AR, AL) rs = [None] * (d + 1) rs[d - 1] = tm.eps_r_op_1s(rR, AR, AR, op2) for k in xrange(d - 1, 0, -1): rs[k - 1] = tm.eps_r_noop(rs[k], AR, AR) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], AR, B)) res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, AR, B, op2)) print 2, res #Terms 3, 4, 6, 7, b ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(B2L, AL, AR, op1) + tm.eps_l_op_1s(lL, AL, B, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AL, AR) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, AR)) res[n] += m.adot(ls[n - 1], tm.eps_r_op_1s(rR, B, AR, op2)) print 3, res #Term 8 ls = [None] * (d + 1) ls[0] = tm.eps_l_op_1s(lL, AL, AL, op1) for k in xrange(1, d + 1): ls[k] = tm.eps_l_noop(ls[k - 1], AL, AL) for n in xrange(2, d + 1): for k in xrange(2, n): res[n] += m.adot(ls[k - 1], tm.eps_r_noop(rs[-(n + 1):][k], B, B)) res[n] -= g[n] print 4, res #Terms 9 and 10 for n in xrange(2, d + 1): for k in xrange(2, n): lj = tm.eps_l_noop(ls[k - 1], AL, B) for j in xrange(k + 1, n): res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], B, AR)) lj = tm.eps_l_noop(lj, AL, AR) res[n] += m.adot(lj, tm.eps_r_op_1s(rR, B, AR, op2)) lj = tm.eps_l_noop(ls[k - 1], B, AL) for j in xrange(k + 1, n): res[n] += m.adot(lj, tm.eps_r_noop(rs[-(n + 1):][j], AR, B)) lj = tm.eps_l_noop(lj, AL, AR) res[n] += m.adot(lj, tm.eps_r_op_1s(rR, AR, B, op2)) print 5, res #Term 11 res[0] += m.adot( tm.eps_l_op_1s(lL, AL, AL, op1.dot(op2) - g[0] * sp.eye(len(op1))), BBR) for n in xrange(1, d + 1): res[n] += m.adot(tm.eps_l_op_1s(ls[n - 1], AL, AL, op2), BBR) res[n] -= g[n] return res
def calc_BHB_prereq(self, tdvp, tdvp2): """Calculates prerequisites for the application of the effective Hamiltonian in terms of tangent vectors. This is called (indirectly) by the self.excite.. functions. Parameters ---------- tdvp2: EvoMPS_TDVP_Uniform Second state (may be the same, or another ground state). Returns ------- A lot of stuff. """ l = tdvp.l[0] r_ = tdvp2.r[0] r__sqrt = tdvp2.r_sqrt[0] r__sqrt_i = tdvp2.r_sqrt_i[0] A = tdvp.A[0] A_ = tdvp2.A[0] #Note: V has ~ D**2 * q**2 elements. We avoid making any copies of it except this one. # This one is only needed because low-level routines force V_[s] to be contiguous. # TODO: Store V instead of Vsh in tdvp_uniform too... V_ = sp.transpose(tdvp2.Vsh[0], axes=(0, 2, 1)).conj().copy(order='C') if self.ham_sites == 2: #eyeham = m.eyemat(self.q, dtype=sp.complex128) eyeham = sp.eye(self.q, dtype=sp.complex128) #diham = m.simple_diag_matrix(sp.repeat([-tdvp.h_expect.real], self.q)) diham = -tdvp.h_expect.real * sp.eye(self.q, dtype=sp.complex128) _ham_tp = self.ham_tp + [[diham, eyeham]] #subtract norm dof Ao1 = get_Aop(A, _ham_tp, 2, conj=False) AhlAo1 = [ tm.eps_l_op_1s(l, A, A, o1.conj().T) for o1, o2 in _ham_tp ] A_o2c = get_Aop(A_, _ham_tp, 1, conj=True) Ao1c = get_Aop(A, _ham_tp, 0, conj=True) A_Vr_ho2 = [ tm.eps_r_op_1s(r__sqrt, A_, V_, o2) for o1, o2 in _ham_tp ] A_A_o12c = get_A_ops(A_, A_, _ham_tp, conj=True) A_o1 = get_Aop(A_, _ham_tp, 2, conj=False) tmp = sp.empty((A_.shape[1], V_.shape[1]), dtype=A.dtype, order='C') tmp2 = sp.empty((A_.shape[1], A_o2c[0].shape[1]), dtype=A.dtype, order='C') rhs10 = 0 for al in xrange(len(A_o1)): tmp2 = tm.eps_r_noop_inplace(r_, A_, A_o2c[al], tmp2) tmp3 = m.mmul(tmp2, r__sqrt_i) rhs10 += tm.eps_r_noop_inplace(tmp3, A_o1[al], V_, tmp) return V_, AhlAo1, A_o2c, Ao1, Ao1c, A_Vr_ho2, A_A_o12c, rhs10, _ham_tp elif self.ham_sites == 3: return