def tensor_train_template(init_rho, pb_index, rank=1): """Get rho_n from rho in a Tensor Train representation. Parameters ---------- rho : np.ndarray """ n_vec = np.zeros((rank, ), dtype=DTYPE) n_vec[0] = 1.0 root_array = np.tensordot(init_rho, n_vec, axes=0) root = Tensor(name='root', array=root_array, axis=None) max_terms = len(pb_index) # +2: i and j root[0] = (Leaf(name=max_terms), 0) root[1] = (Leaf(name=max_terms + 1), 0) for i in pb_index: assert rank <= i train = [root] for k in range(max_terms): if k < max_terms - 1: array = np.eye(rank, pb_index[k] * rank) array = np.reshape(array, (rank, -1, rank)) else: array = np.eye(rank, pb_index[k]) spf = Tensor(name=k, array=array, axis=0) l = Leaf(name=k) spf[0] = (train[-1], 2) spf[1] = (l, 0) train.append(spf) return root
def heisenberg(N, J=1.0, Jz=1.0, h=0): r"""Generate a MPO for Heisenberg Model. .. math:: H = \sum^{N-2}_{i=0} \frac{J}{2} (S^+_i S^-_{i+1} + S^-_i S^+_{i+1}) + J_z S^z_i S^z_{i+1} - \sum^{N-1}_{i=0} h S^z_i For 1-D antiferromagnetic, :math:`J = J_z = 1`. Parameters ---------- N : int number of sites. J : float coupling constant. Jz : float coupling constant in z-direction. h : float external magnetic field. Returns ------- mpo : [(5, 5, 2, 2) ndarray] A list of MPO matrixes. """ # Local operators I = np.eye(2) Z = np.zeros((2, 2)) Sz = np.array([[0.5, 0.0], [0.0, -0.5]]) Sp = np.array([[0., 0.], [1., 0.]]) Sm = np.array([[0., 1.], [0., 0.]]) # left-hand edge: 1*5 Wfirst = np.array( [[-h * Sz, (J / 2.) * Sm, (J / 2.) * Sp, (Jz / 2.) * Sz, I]]) # mid: 5*5 W = np.array([[I, Z, Z, Z, Z], [Sp, Z, Z, Z, Z], [Sm, Z, Z, Z, Z], [Sz, Z, Z, Z, Z], [-h * Sz, (J / 2.) * Sm, (J / 2.) * Sp, (Jz / 2.) * Sz, I]]) # right-hand edge: 5*1 Wlast = np.array([[I], [Sp], [Sm], [Sz], [-h * Sz]]) mpo = [Wfirst] + ([W] * (N - 2)) + [Wlast] return mpo
def annihilator(self, k): """Acting on 0-th index""" dim = self.n_dims[k] lower = np.eye(dim, k=-1) sqrt_n = np.diag(np.sqrt(np.arange(dim))) return sqrt_n @ lower
def creator(self, k): """Acting on 0-th index""" dim = self.n_dims[k] raiser = np.eye(dim, k=1) sqrt_n = np.diag(np.sqrt(np.arange(dim))) return raiser @ sqrt_n
def _lower(self, k): """Acting on 0-th index""" dim = self.n_dims[k] sqrt_n = np.diag(np.sqrt(np.arange(dim, dtype=DTYPE))) return sqrt_n @ np.eye(dim, k=-1, dtype=DTYPE)
def _lower(self, k): """Acting on 0-th index""" dim = self.n_dims[k] return np.eye(dim, k=1, dtype=DTYPE)
def _raiser(self, k): """Acting on 0-th index""" dim = self.n_dims[k] return np.eye(dim, k=1)