Esempio n. 1
0
 def _system_site_mpo(self, h, tau):
     """
     :param h: System site local operator
     :param tau: timestep
     :return: trotterized exponential in mpo form for the system site and the ancilla
     """
     if h is None:
         return mp.chain([
             mp.eye(1, self.shape[self.system_index][0]),
             mp.eye(1, self.shape[self.system_index][1])
         ])
     propagator = expm(-1j * tau * h)
     propagator = propagator.reshape(self.shape[self.system_index][0],
                                     self.shape[self.system_index][0])
     # Add identity to ancilla bond
     mpo = mp.chain([
         mp.MPArray.from_array_global(propagator, ndims=2),
         mp.eye(1, self.shape[self.system_index][1])
     ])
     return self._compress_mpo(mpo)
Esempio n. 2
0
    def _build_identities(self):
        """
            Helper function, that builds suitable identity mpos for the first and the last site of the chain.
            For mpo and mps evolution we may just build them from the shape. For pmps evolution
            we have to group the legs of the two site identities to a single site
        :return: id0, idL (identity on the first site and identity for the last site respectively)
        """
        if self.ancilla_sites:
            id0 = mp.eye(2, self.shape[0])
            # Group together to a single first site with two legs
            id0 = id0.group_sites(2)

            idL = mp.eye(len(self.shape[self.L - 1]), self.shape[self.L - 1])
            # Group together to a single last site with two legs
            idL = idL.group_sites(2)
        else:
            id0 = mp.eye(1, self.shape[0][0])

            idL = mp.eye(1, self.shape[self.L - 1][0])
        return id0, idL
Esempio n. 3
0
def get_maximally_mixed_mpo(dims, normalized=False):
    """
        Generates a maximally mixed state as mpo embedded on a chain with physical dimensions specified by dims.
    :param dims: iterable of site local physical leg dimensions of the chain in which to embed
    :param normalized: Set True to return a normalized state
    :return: maximally mixed state as MPO
    """
    mm_mpo = mp.eye(len(dims), dims)
    if not normalized:
        return mm_mpo
    else:
        return mm_mpo / mp.trace(mm_mpo)
Esempio n. 4
0
def get_maximally_mixed_pmps(dims, normalized=False):
    """
        Generates a maximally mixed state as pmps embedded on a chain with physical dimensions specified by dims
        The ancilla dimension are the same as the physical dimension on each site.
    :param dims: iterable of site local physical leg dimensions of the chain in which to embed
    :param normalized: Set True to return a normalized state
    :return: maximally mixed state as PMPS
    """
    mm_pmps = mp.eye(len(dims), dims)
    if not normalized:
        return mm_pmps
    else:
        return mm_pmps / mp.norm(mm_pmps)
Esempio n. 5
0
 def _mpo_from_hi(self, hi, tau, bond):
     """
         Convenience function, which allows to split mpo generation for 0T and finite T.
         Generates mpos for e^(-j*\tau*hi) as matrix exponential (uses scipy expm)
         For mps and mpo we just build e^(-j*\tau*hi) for the physical legs and generate the mpo.
         For pmps we first generate
         U^((s1, s2, s3), (s1', s2', s3')) = U^((s1, s3), (s1', s3')) * delta^(s2, s2')
         for each hi with U^((s1, s3), (s1', s3')) = e^(-j*tau*hi)
         with s2/s2' ancilla site. And then append a delta^(s4, s4') at the end for the second ancilla.
     :param hi: Bond operator to generate matrix exponential from
     :param tau: timestep for propagator
     :param bond: Bond index (i) for hi
     :return: e^(-j*tau*hi) in mpo form. For mps/mpo propagation is a two site two legs each operator
              for pmps propagation is a two site four legs (two physical, two ancilla on each site)
              ready for application to a state.
              Pre-compresses the operator if op_compression_kwargs not None
     """
     # Generate e^(-j*tau*hi)
     physical_legs_exp = expm(-1j * tau * hi)
     # Tensorial shape of hi for the two physical sites i and i+1 in global form
     physical_legs_tensor_shape = (self.shape[bond][0], self.shape[bond + 1][0],
                                   self.shape[bond][0], self.shape[bond + 1][0])
     physical_legs_exp = physical_legs_exp.reshape(physical_legs_tensor_shape)
     if not self.ancilla_sites:
         # Need only consider physical legs here
         mpo = mp.MPArray.from_array_global(physical_legs_exp, ndims=2)
     else:
         # Here we need to consider that there is an ancilla between the physical sites for which
         # physical_legs_exp was constructed.
         ldim_first_ancilla = self.shape[bond][1]
         ldim_second_ancilla = self.shape[bond + 1][1]
         # U^((s1, s3), (s1', s3')) * delta^(s2, s2')
         physical_and_first_ancilla = np.tensordot(physical_legs_exp, np.eye(ldim_first_ancilla), axes=0)
         # Slide indices s2 and s2' between s1 and s3/1' and s3' respectively
         physical_and_first_ancilla = np.moveaxis(physical_and_first_ancilla, [-2, -1], [1, 4])
         # Add identity for second ancilla bond
         mpo = mp.chain([mp.MPArray.from_array_global(physical_and_first_ancilla, ndims=2),
                         mp.eye(1, ldim_second_ancilla)]).group_sites(2)
     if self.op_compression_kwargs is not None:
         mpo.compress(**self.op_compression_kwargs)
     return mpo
Esempio n. 6
0
    def _mpo_from_hi(self, hi, tau, lbond, rbond):
        """
            Generates
            U^{(s1, s2, s3), (s1', s2', s3')} = U^{(s1, s3), (s1', s3')} * delta^{s2, s2'}
            for each hi with U^{(s1, s3), (s1', s3')} = e^(-1j*\tau*hi)
            with s2/s2' ancilla site. And then appends a delta^{s4, s4'} at the end for the second ancilla.
        :param hi: Bond operator (tuple of (Eigvals, Eigvecs))
        :param tau: timestep for propagator
        :param lbond: Bond index (i) for the left site in hi
        :param rbond: Bond index for the right site in hi
        :return: e^(-1j*\tau*hi) in mpo form. A two site four legs (two physical, two ancilla on each site)
                 ready for application to a state
        """

        # Generate e^(-j*tau*hi)
        physical_legs_exp = expm(-1j * tau * hi)
        # Tensorial shape of hi for the two physical sites i and i+1 in global form
        physical_legs_tensor_shape = (self.shape[lbond][0],
                                      self.shape[rbond][0],
                                      self.shape[lbond][0],
                                      self.shape[rbond][0])
        physical_legs_exp = physical_legs_exp.reshape(
            physical_legs_tensor_shape)
        # Here we need to consider that there is an ancilla between the physical sites for which
        # physical_legs_exp was constructed.
        ldim_first_ancilla = self.shape[lbond][1]
        ldim_second_ancilla = self.shape[rbond][1]
        # U^((s1, s3), (s1', s3')) * delta^(s2, s2')
        physical_and_first_ancilla = np.tensordot(physical_legs_exp,
                                                  np.eye(ldim_first_ancilla),
                                                  axes=0)
        # Slide indices s2 and s2' between s1 and s3/1' and s3' respectively
        physical_and_first_ancilla = np.moveaxis(physical_and_first_ancilla,
                                                 [-2, -1], [1, 4])
        # Add identity for second ancilla bond
        mpo = mp.chain([
            mp.MPArray.from_array_global(physical_and_first_ancilla, ndims=2),
            mp.eye(1, ldim_second_ancilla)
        ])
        return self._compress_mpo(mpo)