def check_mps_norm1(self, if_print=False):
     # check if the MPS is norm-1
     norm = self.norm_mps()
     if abs(norm - 1) > 1e-14:
         print_error('The norm is MPS is %g away from 1' % abs(norm - 1))
     if if_print:
         cprint('The norm of MPS is %g' % norm, 'cyan')
Example #2
0
 def update_effect_from_op1_to_op2(self, sn, snn, p0, q0, p1):
     # here, we have p0 < q0 < p1, or p1 >= q0 > p0 (on the same side of the RG endpoint)
     if q0 < p1:
         v = self.get_effective_operators_one_body(sn, p0, q0)
         v = T_module.bound_vec_operator_left2right(self.mps[q0],
                                                    self.operators[snn], v)
         self.add_key_and_pos('two', (sn, snn, p0, q0, q0 + 1), v)
         for n in range(q0 + 1, p1):
             v = self.update_effect_op_l0_to_l1(n,
                                                n + 1,
                                                v,
                                                is_update_op=False)
             self.add_key_and_pos('two', (sn, snn, p0, q0, n + 1), v)
     elif p1 <= p0:
         v = self.get_effective_operators_one_body(snn, q0, p0 + 1)
         v = T_module.bound_vec_operator_right2left(self.mps[p0],
                                                    self.operators[sn], v)
         self.add_key_and_pos('two', (sn, snn, p0, q0, p0), v)
         for n in range(p0 - 1, p1 - 1, -1):
             v = self.update_effect_op_l0_to_l1(n,
                                                n - 1,
                                                v,
                                                is_update_op=False)
             self.add_key_and_pos('two', (sn, snn, p0, q0, n), v)
     else:
         # if this happen, there must be a logic bug
         v = None
         print_error('LogicBug detected. Please check')
     return v
Example #3
0
def absorb_matrices2tensor(tensor, mats, bonds=np.zeros(0), mat_bond=-1):
    # default: contract the 1st bond of mat with tensor
    nm = len(mats)  # number of matrices to be contracted
    if is_debug:
        if nm != tensor.ndim:
            print_error(
                'InputError: the number of matrices should be equal to the number of indexes of tensor'
            )
    if bonds.size == 0:  # set default of bonds: contract all matrices in order, starting from the 0th bond
        bonds = np.arange(0, nm)
    if mat_bond < 0:  # set default of mat_bond: contract the 1st bond of each matrix
        mat_bond = np.zeros((nm, 1))
    for i in range(
            0,
            nm):  # permute if the second bond of a matrix is to be contracted
        if mat_bond[i, 0] == 1:
            mats[i] = mats[i].T
    # check if full_fast function can be used
    if np.array_equiv(np.sort(bonds), np.arange(0, nm)):
        order = np.argsort(bonds)
        mats = sort_list(mats, order)
        # this full_fast function can be used when each bond has a matrix which are arranged in the correct order
        tensor = absorb_matrices2tensor_full_fast(tensor, mats)
    else:
        # can be optimized
        for i in range(0, nm):
            tensor = absorb_matrix2tensor(tensor, mats[i], bonds[i])
    return tensor
Example #4
0
 def get_effective_operator_two_body(self, sn, snn, p0, q0, p1):
     # the self.operators[sn]  is originally at p0-th site
     # the self.operators[ssn] is originally at q0-th site
     # the effective two-body operator is at the p1-th bond
     # here, we have p0 < q0 <= p1, or p1 >= q0 > p0 (on the same side of the RG endpoint)
     if p0 > q0:  # make sure p0 < q0
         p0, q0 = q0, p0
         sn, snn = snn, sn
     key2 = self.key_effective_operators((sn, snn, p0, q0, p1))
     if key2 in self.effect_ss:
         return self.effect_ss[key2]
     elif q0 == p1:
         print_error('LogicBug detected: please check')
     else:
         return self.update_effect_from_op1_to_op2(sn, snn, p0, q0, p1)
 def update_tensor_handle_dmrg_1site(self,
                                     tensor,
                                     p,
                                     operators,
                                     index1,
                                     index2,
                                     coeff1,
                                     coeff2,
                                     tau,
                                     tol=1e-12):
     # Very inefficient!!!
     # function handle to put in eigs, to update the p-th tensor
     # index1: one-body interactions, index2: two-body interactions
     # one-body terms: index1[n, 1]-th operator is at the index1[n, 0]-th site
     # tne-body terms: index2[n, 2]-th operator is at the index2[n, 0]-th site
     # tne-body terms: index2[n, 3]-th operator is at the index2[n, 1]-th site
     if self._debug and p != self.center:
         print_error(
             'CenterError: the tensor must be at the orthogonal center before '
             'defining the function handle', 'magenta')
     tensor = tensor.reshape(self.virtual_dim[p], self.phys_dim,
                             self.virtual_dim[p + 1])
     tensor1 = tensor.copy()
     nh1 = index1.shape[0]  # number of two-body Hamiltonians
     for n in range(0, nh1):
         op = operators[index1[n, 1]]
         # if the coefficient is too small, ignore its contribution
         if abs(coeff1[n]) > tol and np.linalg.norm(op.reshape(1,
                                                               -1)) > tol:
             v_left, v_middle, v_right = self.environment_s1(
                 p, op, index1[n, 0])
             if self._debug:
                 self.check_environments(v_left, v_middle, v_right, p)
             tensor1 -= tau * coeff1[n] * T_module.absorb_matrices2tensor(
                 tensor, [v_left, v_middle, v_right])
     nh2 = index2.shape[0]  # number of two-body Hamiltonians
     for n in range(0, nh2):
         # if the coefficient is too small, ignore its contribution
         if abs(coeff2[n]) > tol:
             op = [operators[index2[n, 2]], operators[index2[n, 3]]]
             v_left, v_middle, v_right = self.environment_s1_s2(
                 p, op, index2[n, :2])
             if self._debug:
                 self.check_environments(v_left, v_middle, v_right, p)
             tensor1 -= tau * coeff2[n] * T_module.absorb_matrices2tensor(
                 tensor, [v_left, v_middle, v_right])
     return tensor1.reshape(-1, 1)
 def effective_hamiltonian_dmrg(self,
                                p,
                                operators,
                                index1,
                                index2,
                                coeff1,
                                coeff2,
                                tol=1e-12):
     if self._debug and p != self.center:
         print_error(
             'CenterError: the tensor must be at the orthogonal center before '
             'defining the function handle', 'magenta')
     nh1 = index1.shape[0]
     s = [self.virtual_dim[p], self.phys_dim, self.virtual_dim[p + 1]]
     dim = np.prod(s)
     h_effect = np.zeros((dim, dim))
     for n in range(0, nh1):
         # if the coefficient is too small, ignore its contribution
         if abs(coeff1[n]) > tol and np.linalg.norm(
                 operators[index1[n, 1]].reshape(1, -1)) > tol:
             v_left, v_middle, v_right = self.environment_s1(
                 p, operators[index1[n, 1]], index1[n, 0])
             if self._debug:
                 self.check_environments(v_left, v_middle, v_right, p)
             h_effect += coeff1[n] * np.kron(np.kron(v_left, v_middle),
                                             v_right)
     nh2 = index2.shape[0]  # number of two-body Hamiltonians
     for n in range(0, nh2):
         # if the coefficient is too small, ignore its contribution
         if abs(coeff2[n]) > tol:
             v_left, v_middle, v_right = \
                 self.environment_s1_s2(p, [operators[index2[n, 2]], operators[index2[n, 3]]], index2[n, :2])
             if self._debug:
                 self.check_environments(v_left, v_middle, v_right, p)
             h_effect += coeff2[n] * np.kron(np.kron(v_left, v_middle),
                                             v_right)
     h_effect = (h_effect + h_effect.conj().T) / 2
     return h_effect, s