def onebody_sum_mpo(terms, output_label=None): """ Construct an MPO from a sum of onebody operators, using the recipe from the Supplemental Material of [1]_ (Eqs. (3) and (4)) Parameters --------- terms : list A list containing the terms in the sum. Each term should be 2D array-like, e.g., a rank-two Tensor or numpy array. output_label : str, optional Specify the label corresponding to the output index. Must be the same for each element of `terms`. If not specified the first index is taken to be the output index. Returns ------ MatrixProductOperator References ---------- .. [1] E. Sanchez-Burillo et al., Phys. Rev. Lett. 113, 263604 (2014) """ tensors = [] for i, term1 in enumerate(terms): if output_label is not None: term = term1.copy() term.move_index(output_label, 0) else: term = term1 if i == 0: B = np.zeros(shape=term.shape + (2, ), dtype=complex) for k in range(term.shape[0]): for l in range(term.shape[1]): B[k, l, :] = [term[k, l], k == l] tensors.append(tnc.Tensor(B, ['physout', 'physin', 'right'])) elif i == len(terms) - 1: B = np.zeros(shape=term.shape + (2, ), dtype=complex) for k in range(term.shape[0]): for l in range(term.shape[1]): B[k, l, :] = [k == l, term[k, l]] tensors.append(tnc.Tensor(B, ['physout', 'physin', 'left'])) else: B = np.zeros(shape=term.shape + (2, 2), dtype=complex) for k in range(term.shape[0]): for l in range(term.shape[1]): B[k, l, :, :] = [[k == l, 0], [term[k, l], k == l]] tensors.append( tnc.Tensor(B, ['physout', 'physin', 'left', 'right'])) return onedim.MatrixProductOperator(tensors, left_label='left', right_label='right', physin_label='physin', physout_label='physout')
def init_mps_logical(nsites, basis_state, physdim, left_label='left', right_label='right', phys_label='phys'): """ Create an MPS with `nsites` sites in the logical basis state |ijk..l>. Parameters ---------- nsites : int basis_state : int or list of ints Site `i` will be in the state |`basis_state[i]`> (or simply |`basis_state`> if a single int is provided). physdim : int or list of ints left_label : str right_label : str phys_label : str """ if not np.iterable(physdim): physdim = [physdim] * nsites tensors = [] for j in range(nsites): t = np.zeros(physdim[j]) t[basis_state[j]] = 1.0 t = tnc.Tensor(t.reshape(physdim[j], 1, 1), [phys_label, left_label, right_label]) tensors.append(t) return onedim.MatrixProductState(tensors, left_label=left_label, right_label=right_label, phys_label=phys_label)
def init_mps_allzero(nsites, physdim, left_label='left', right_label='right', phys_label='phys'): """ Create an MPS with `nsites` sites in the "all zero" state |00..0>. Parameters ---------- nsites : int physdim : int or list of ints left_label : str right_label : str phys_label : str """ if not np.iterable(physdim): physdim = [physdim] * nsites tensors = [] for j in range(nsites): t = np.zeros(physdim[j]) t[0] = 1.0 t = tnc.Tensor(t.reshape(physdim[j], 1, 1), [phys_label, left_label, right_label]) tensors.append(t) return onedim.MatrixProductState(tensors, left_label=left_label, right_label=right_label, phys_label=phys_label)
def init_mps_random(nsites, physdim, bonddim=1, left_label='left', right_label='right', phys_label='phys'): """ Create an MPS with `nsites` sites and random tensors with physical dimensions given by `physdim` and bond dimensions given by `bonddim`. Open boundary conditions are used. The MPS is not normalized. Parameters ---------- nsites : int physdim : int or list of ints bonddim : int or list of ints, optional The nth element of `bonddim` determines the right and left index of the tensors at sites n and n+1, respectively. The length of `bonddim` should be `nsites`-1. If `bonddim` is an int this is this is used for all bonds. left_label : str right_label : str phys_label : str """ if not np.iterable(physdim): physdim = [physdim] * nsites if not np.iterable(bonddim): bonddim = [bonddim] * (nsites - 1) bonddim = [1] + bonddim + [1] tensors = [] for i in range(nsites): rt = tnc.Tensor(np.random.rand(physdim[i], bonddim[i], bonddim[i + 1]), [phys_label, left_label, right_label]) # Normalize matrix to avoid norm blowing up U, S, V = tnc.tensor_svd(rt, [phys_label, left_label]) S.data = S.data / S.data[0, 0] rt = U["svd_in", ] * S["svd_out", ] rt = rt["svd_in", ] * V["svd_out", ] tensors.append(rt) return onedim.MatrixProductState(tensors, left_label=left_label, right_label=right_label, phys_label=phys_label)