def expect_1s_1s(self, op1, op2, n1, n2, return_intermediates=False): """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). return_intermediates : bool Whether to return results for intermediate sites. Returns ------- expval : complex128 or sequence of complex128 The expectation value (data type may be complex), or values if return_intermediates == True. """ 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])) d = n2 - n1 res = sp.zeros((d + 1), dtype=sp.complex128) lj = tm.eps_l_op_1s(self.l[n1 - 1], self.A[n1], self.A[n1], op1) if return_intermediates: res[0] = self.expect_1s(op1.dot(op1), n1) for j in range(1, d + 1): if return_intermediates or j == d: lj_op = tm.eps_l_op_1s(lj, self.A[n1 + j], self.A[n1 + j], op2) res[j] = m.adot(lj_op, self.r[n1 + j]) if j < d: lj = tm.eps_l_noop(lj, self.A[n1 + j], self.A[n1 + j]) if return_intermediates: return res else: return res[-1]
def expect_1s_1s(self, op1, op2, n1, n2, return_intermediates=False): """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). return_intermediates : bool Whether to return results for intermediate sites. Returns ------- expval : complex128 or sequence of complex128 The expectation value (data type may be complex), or values if return_intermediates == True. """ 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])) d = n2 - n1 res = sp.zeros((d + 1), dtype=sp.complex128) lj = tm.eps_l_op_1s(self.l[n1 - 1], self.A[n1], self.A[n1], op1) if return_intermediates: res[0] = self.expect_1s(op1.dot(op1), n1) for j in xrange(1, d + 1): if return_intermediates or j == d: lj_op = tm.eps_l_op_1s(lj, self.A[n1 + j], self.A[n1 + j], op2) res[j] = m.adot(lj_op, self.r[n1 + j]) if j < d: lj = tm.eps_l_noop(lj, self.A[n1 + j], self.A[n1 + j]) if return_intermediates: return res else: return res[-1]
def GenerateSineArray(gridShape, dimension, randomPhase = False): if randomPhase: phase = numpy.random.random()*2.*pi else: phase = 0. result = fromfunction(lambda x: sin(pi*(x)/gridShape[0]+phase), [gridShape[0]]) for dim in range(1, dimension): if randomPhase: phase = numpy.random.random()*2.*pi else: phase = 0. temp = fromfunction(lambda x: sin(pi*(x)/gridShape[dim]+phase), [gridShape[dim]]) result = outer(result, temp) return result
def expect_2s(self, op, n): """Computes the expectation value of a nearest-neighbour two-site operator. The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array such that op[s, t, u, v] = <st|op|uv> or a function of the form op(s, t, u, v) = <st|op|uv>. Parameters ---------- o : ndarray or callable The operator array or function. n : int The leftmost site number (operator acts on n, n + 1). """ A = self.get_A(n) Ap1 = self.get_A(n + 1) AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.get_r(n + 1), C, AA) return mm.adot(self.get_l(n - 1), res)
def expect_2s(self, op, n, AA=None): """Computes the expectation value of a nearest-neighbour two-site operator. The operator should be a q[n] x q[n + 1] x q[n] x q[n + 1] array such that op[s, t, u, v] = <st|op|uv> or a function of the form op(s, t, u, v) = <st|op|uv>. The state must be up-to-date -- see self.update()! Parameters ---------- op : ndarray or callable The operator array or function. n : int The leftmost site number (operator acts on n, n + 1). Returns ------- expval : floating point number The expectation value (data type may be complex) """ A = self.A[n] Ap1 = self.A[n + 1] if AA is None: AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], C, AA) return m.adot(self.l[n - 1], res)
def calc_B_1s_diss(self,op,n): """Applies a single-site operator to a single site and returns the parameter tensor for that site after the change with the change in the norm of the state projected out. Parameters ---------- op : ndarray or callable The single-site operator. See self.expect_1s(). n: int The site to apply the operator to. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) newAn = sp.zeros_like(self.A[n]) for s in range(self.q[n]): for t in range(self.q[n]): newAn[s] += self.A[n][t] * op[s, t] r_nm1 = TDVP.tm.eps_r_noop(self.r[n], newAn, newAn) ev = mm.adot(self.l[n - 1], r_nm1) newAn -= ev * self.A[n] #norm-fixing return newAn
def calc_B_1s_diss(self, op, n): """Applies a single-site operator to a single site and returns the parameter tensor for that site after the change with the change in the norm of the state projected out. Parameters ---------- op : ndarray or callable The single-site operator. See self.expect_1s(). n: int The site to apply the operator to. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) newAn = sp.zeros_like(self.A[n]) for s in xrange(self.q[n]): for t in xrange(self.q[n]): newAn[s] += self.A[n][t] * op[s, t] r_nm1 = TDVP.tm.eps_r_noop(self.r[n], newAn, newAn) ev = mm.adot(self.l[n - 1], r_nm1) newAn -= ev * self.A[n] #norm-fixing return newAn
def expect_3s(self, op, n): """Computes the expectation value of a nearest-neighbour three-site operator. The operator should be a q[n] x q[n + 1] x q[n + 2] x q[n] x q[n + 1] x q[n + 2] array such that op[s, t, u, v, w, x] = <stu|op|vwx> or a function of the form op(s, t, u, v, w, x) = <stu|op|vwx>. The state must be up-to-date -- see self.update()! Parameters ---------- op : ndarray or callable The operator array or function. n : int The leftmost site number (operator acts on n, n + 1, n + 2). Returns ------- expval : floating point number The expectation value (data type may be complex) """ A = self.A[n] Ap1 = self.A[n + 1] Ap2 = self.A[n + 2] AAA = tm.calc_AAA(A, Ap1, Ap2) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], Ap2.shape[0], A.shape[0], Ap1.shape[0], Ap2.shape[0])) C = tm.calc_C_3s_mat_op_AAA(op, AAA) res = tm.eps_r_op_3s_C123_AAA456(self.r[n + 2], C, AAA) return m.adot(self.l[n - 1], res)
def expect_1s_diss(self,op,n): """Applies a single-site operator to a single site and returns the value after the change. In contrast to mps_gen.apply_op_1s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The single-site operator. See self.expect_1s(). n: int The site to apply the operator to. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) newAn = sp.zeros_like(self.A[n]) for s in xrange(self.q[n]): for t in xrange(self.q[n]): newAn[s] += self.A[n][t] * op[s, t] return newAn
def apply_op_1s(self, op, n, do_update=True): """Applies a single-site operator to a single site. By default, this performs self.update(), which also restores state normalization. Parameters ---------- op : ndarray or callable The single-site operator. See self.expect_1s(). n: int The site to apply the operator to. do_update : bool Whether to update after applying the operator. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) newAn = sp.zeros_like(self.A[n]) for s in xrange(self.q[n]): for t in xrange(self.q[n]): newAn[s] += self.A[n][t] * op[s, t] self.A[n] = newAn if do_update: self.update()
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_diss(self, op, n): """Applies a single-site operator to a single site and returns the value after the change. In contrast to mps_gen.apply_op_1s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The single-site operator. See self.expect_1s(). n: int The site to apply the operator to. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) newAn = sp.zeros_like(self.A[n]) for s in xrange(self.q[n]): for t in xrange(self.q[n]): newAn[s] += self.A[n][t] * op[s, t] return newAn
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 _create_distance_matrix(self, size): h, w = size def freq(yy, xx): f1 = np.minimum(yy, h - yy) f2 = np.minimum(xx, w - xx) return np.sqrt(f1**2 + f2**2) return scipy.fromfunction(freq, (h, w))
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 GenerateGaussianRandomArray(gridShape, temp, sigma): dimension = len(gridShape) if dimension == 1: kfactor = fromfunction(lambda kz: exp(-0.5*(sigma*kz)**2),[gridShape[0]/2+1,]) ktemp = fft.rfft(temp) ktemp *= kfactor data = fft.irfft(ktemp) elif dimension == 2: X,Y = gridShape kfactor = fromfunction(lambda kx,ky: exp(-0.5*sigma**2*((kx*(kx<X/2)+(X-kx)*(kx>=X/2))**2+ky**2)),[X,Y/2+1]) ktemp = fft.rfftn(temp) ktemp *= kfactor data = fft.irfftn(ktemp) elif dimension == 3: X,Y,Z = gridShape kfactor = fromfunction(lambda kx,ky,kz: exp(-0.5*sigma**2*( (kx*(kx<X/2)+(X-kx)*(kx>=X/2))**2 + \ (ky*(ky<Y/2)+(Y-ky)*(ky>=Y/2))**2 + kz**2)),[X,Y,Z/2+1]) ktemp = fft.rfftn(temp) ktemp *= kfactor data = fft.irfftn(ktemp) return data
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(range(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_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 calc_C(self, n_low=-1, n_high=-1): """Generates the C tensors used to calculate the K's and ultimately the B's. This is called automatically by self.update(). C[n] contains a contraction of the Hamiltonian self.ham with the parameter tensors over the local basis indices. This is prerequisite for calculating the tangent vector parameters B, which optimally approximate the exact time evolution. These are to be used on one side of the super-operator when applying the nearest-neighbour Hamiltonian, similarly to C in eqn. (44) of arXiv:1103.0936v2 [cond-mat.str-el], for the non-norm-preserving case. Makes use only of the nearest-neighbour Hamiltonian, and of the A's. C[n] depends on A[n] through A[n + self.ham_sites - 1]. """ if self.ham is None: return 0 if n_low < 1: n_low = 1 if n_high < 1: n_high = self.N - self.ham_sites + 1 for n in xrange(1, self.N): self.AA[n] = tm.calc_AA(self.A[n], self.A[n + 1]) if self.ham_sites == 3: for n in xrange(1, self.N - 1): self.AAA[n] = tm.calc_AAA_AA(self.AA[n], self.A[n + 2]) else: self.AAA.fill(None) for n in xrange(n_low, n_high + 1): if callable(self.ham): ham_n = lambda *args: self.ham(n, *args) ham_n = sp.vectorize(ham_n, otypes=[sp.complex128]) ham_n = sp.fromfunction(ham_n, tuple(self.C[n].shape[:-2] * 2)) else: ham_n = self.ham[n] if self.ham_sites == 2: self.C[n] = tm.calc_C_mat_op_AA(ham_n, self.AA[n]) else: self.C[n] = tm.calc_C_3s_mat_op_AAA(ham_n, self.AAA[n])
def expect_string_1s(self, op, n, d): """Calculates the expectation values of finite strings with lengths 1 to d, starting at position n. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q, self.q)) res = sp.zeros((d), dtype=self.A[1].dtype) x = self.l[n - 1] for j in range(n, n + d + 1): Aop = sp.tensordot(op, self.A[j], axes=([1],[0])) x = tm.eps_l_noop(x, self.A[j], Aop) res[j - n - 1] = m.adot(x, self.r[j]) return res
def expect_string_1s(self, op, n, d): """Calculates the expectation values of finite strings with lengths 1 to d, starting at position n. """ if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q, self.q)) res = sp.zeros((d), dtype=self.A[1].dtype) x = self.l[n - 1] for j in xrange(n, n + d + 1): Aop = sp.tensordot(op, self.A[j], axes=([1],[0])) x = tm.eps_l_noop(x, self.A[j], Aop) res[j - n - 1] = m.adot(x, self.r[j]) return res
def calc_C_diss(self, L, n_low=-1, n_high=-1): """Generates the C tensors used to calculate the K's and ultimately the B's. This is called automatically by self.update(). C[n] contains a contraction of the Hamiltonian self.ham with the parameter tensors over the local basis indices. This is prerequisite for calculating the tangent vector parameters B, which optimally approximate the exact time evolution. These are to be used on one side of the super-operator when applying the nearest-neighbour Hamiltonian, similarly to C in eqn. (44) of arXiv:1103.0936v2 [cond-mat.str-el], for the non-norm-preserving case. Makes use only of the nearest-neighbour Hamiltonian, and of the A's. C[n] depends on A[n] through A[n + self.ham_sites - 1]. """ LC = sp.zeros_like(self.C) if L is None: return 0 if n_low < 1: n_low = 1 if n_high < 1: n_high = self.N - self.ham_sites + 1 for n in xrange(n_low, n_high + 1): if callable(L): ham_n = lambda *args: L(n, *args) ham_n = sp.vectorize(ham_n, otypes=[sp.complex128]) ham_n = sp.fromfunction(ham_n, tuple(self.C[n].shape[:-2] * 2)) else: #print "L shape", L.shape ham_n = L.reshape(4, 4, 4, 4) if self.ham_sites == 2: AA = tm.calc_AA(self.A[n], self.A[n + 1]) LC[n] = tm.calc_C_mat_op_AA(ham_n, AA) else: AAA = tm.calc_AAA(self.A[n], self.A[n + 1], self.A[n + 2]) LC[n] = tm.calc_C_3s_mat_op_AAA(ham_n, AAA) return LC
def apply_op_1s(self, op, n): """Applies a one-site operator op to site n. Can be used to create excitations. """ if not (0 < n <= self.N): raise ValueError("Operators can only be applied to sites 1 to N!") newA = sp.zeros_like(self.A[n]) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) for s in xrange(self.q[n]): for t in xrange(self.q[n]): newA[s] += self.A[n][t] * op[s, t] self.A[n] = newA
def apply_op_1s(self, op, n): """Applies a one-site operator op to site n. Can be used to create excitations. """ if not (0 < n <= self.N): raise ValueError("Operators can only be applied to sites 1 to N!") newA = sp.zeros_like(self.A[n]) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (self.q[n], self.q[n])) for s in range(self.q[n]): for t in range(self.q[n]): newA[s] += self.A[n][t] * op[s, t] self.A[n] = newA
def expect_2s_diss(self, op, LC, LK, n, AA=None): """Applies a two-site operator to two sites and returns the value after the change. In contrast to mps_gen.apply_op_2s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The two-site operator. See self.expect_2s(). n: int The site to apply the operator to. (It's also applied to n-1.) """ #No neighbors, no fun. if n is 1: return 0 if n is N: return 0 A = self.A[n - 1] Ap1 = self.A[n] if AA is None: AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction( op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) op = op.reshape(4, 4, 4, 4) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], LC, AA) operand = self.l[n - 1] operand = sp.reshape(operand, (1, 16)) operand = sp.reshape(operand, (2, 8)) return mm.mmul(operand, res) return mm.adot(self.l[n - 1], res)
def expect_2s_diss(self, op, LC, LK, n, AA=None): """Applies a two-site operator to two sites and returns the value after the change. In contrast to mps_gen.apply_op_2s, this routine does not change the state itself. Also, this does not perform self.update(). Parameters ---------- op : ndarray or callable The two-site operator. See self.expect_2s(). n: int The site to apply the operator to. (It's also applied to n-1.) """ #No neighbors, no fun. if n is 1: return 0 if n is N: return 0 A = self.A[n-1] Ap1 = self.A[n] if AA is None: AA = tm.calc_AA(A, Ap1) if callable(op): op = sp.vectorize(op, otypes=[sp.complex128]) op = sp.fromfunction(op, (A.shape[0], Ap1.shape[0], A.shape[0], Ap1.shape[0])) op = op.reshape(4,4,4,4) C = tm.calc_C_mat_op_AA(op, AA) res = tm.eps_r_op_2s_C12_AA34(self.r[n + 1], LC, AA) operand = self.l[n-1] operand = sp.reshape(operand, (1,16)) operand = sp.reshape(operand, (2,8)) return mm.mmul(operand,res) return mm.adot(self.l[n - 1], res)
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)