def contract_from_right(R, A, W, B): r"""Tensor contraction from the right hand side.:: -i- + -i- A -j- + | |s | -a- R' = -a- W -b- R | |t | -k- + -k- B -l- + Parameters ---------- R : (b, j, l) ndarray A : (s, i, j) ndarray W : (a, b, s, t) ndarray B : (t, k, l) ndarray Returns ------- R' : {(a, i, k) ndarray, (i, k) ndarray} L'[a, i, k] if ``W`` is not ``None``, otherwise L'[i, k]. """ if W is not None: temp = np.einsum('sij,bjl->sbil', A, R) temp = np.einsum('sbil,abst->tail', temp, W) temp = np.einsum('tail,tkl->aik', temp, B) else: temp = np.einsum('sij,jl->sil', A, R) temp = np.einsum('sil,skl->ik', temp, B) return temp
def contract_from_left(L, A, W, B): r"""Tensor contraction from the left hand side.:: + -j- + -i- A -j- | | |s L'-b- = L -a- W -b- | | |t + -l- + -k- B -l- Parameters ---------- L : (a, i, k) ndarray A : (s, i, j) ndarray W : {(a, b, s, t) ndarray, None} B : (t, k, l) ndarray Returns ------- L' : {(b, j, l) ndarray, (j, l) ndarray} L'[b, j, l] if ``W`` is not ``None``, otherwise L'[j, l]. """ if W is not None: temp = np.einsum('sij,aik->sajk', A, L) temp = np.einsum('sajk,abst->tbjk', temp, W) temp = np.einsum('tbjk,tkl->bjl', temp, B) else: temp = np.einsum('sij,ik->sjk', A, L) temp = np.einsum('sjk,skl->jl', temp, B) return temp
def coarse_grain_mpo(W, X): """Coarse-graining of two site MPO into one site.:: |su |s |u -a- R -c- = -a- W -b- X -c- |tv |t |v Parameters ---------- W : (a, b, s, t) ndarray A MPS matrix. X : (b, c, u, v) ndarray A MPS matrix. Returns ------- R : (a, c, su, tv) ndarray A MPS matrix. """ R = np.einsum("abst,bcuv->acsutv", W, X) sh = [ W.shape[0], # a X.shape[1], # c W.shape[2] * X.shape[2], # su W.shape[3] * X.shape[3] ] # tv return np.reshape(R, sh)
def _move_right(mat, mat_next, _trunc): shape = np.shape(mat) # SVD on mat[si, j] mat = np.reshape(mat, (shape[0] * shape[1], shape[2])) U, S, V = np.linalg.svd(mat, full_matrices=0) # truncated to compress. U, S, V, compress_error = compress_svd(U, S, V, _trunc) mat = np.reshape(U, (shape[0], shape[1], -1)) # U[si, m] SV = np.matmul(np.diag(S), V) mat_next = np.einsum('mj,tjk->tmk', SV, mat_next) return mat, mat_next
def _move_left(mat, mat_prev, _trunc): shape = np.shape(mat) mat = np.reshape( np.transpose(mat, (1, 0, 2)), # mat[i, s, j] (shape[1], shape[0] * shape[2])) # SVD on mat[i, sj] U, S, V = np.linalg.svd(mat, full_matrices=0) # truncated to compress. U, S, V, compress_error = compress_svd(U, S, V, _trunc) mat = np.reshape(V, (-1, shape[0], shape[2])) # V[m, sj] mat = np.transpose(mat, (1, 0, 2)) # mat[s, m, j] US = np.matmul(U, np.diag(S)) mat_prev = np.einsum('rhi,im->rhm', mat_prev, US) return mat, mat_prev
def coarse_grain_mps(A, B): """Coarse-graining of two-site MPS into one site.:: |st |s |t -i- C -k- = -i- A -j- B -k- Parameters ---------- A : (s, i, j) ndarray A MPS matrix. B : (t, j, k) ndarray A MPS matrix. Returns ------- C : (st, i, k) ndarray A MPS matrix. """ shape_C = [A.shape[0] * B.shape[0], A.shape[1], B.shape[2]] C = np.einsum("sij,tjk->stik", A, B) return np.reshape(C, shape_C)
def _matvec(self, A): temp = np.einsum('aij,sik->ajsk', self.L, np.reshape(A, self.io_shape)) temp = np.einsum('ajsk,abst->bjtk', temp, self.W) temp = np.einsum('bjtk,bkl->tjl', temp, self.R) return np.reshape(temp, self.size)