コード例 #1
0
 def evolve(self):
     """
         Perform a Trotterized time evolution step by tau. Renormalizes state after
         one full Trotter-step due to compression.
     :return:
     """
     overlap = self.base_overlap
     if not self.canonicalize_every_step:
         canonicalize_to(self.psi_t, to_cform=self.to_cform)
     for index, trotter_ui in enumerate(self.propagator.trotter_steps):
         self.psi_t = mp.dot(trotter_ui, self.psi_t, self.axes)
         if self.canonicalize_every_step:
             overlap *= self.psi_t.compress(**self.state_compression_kwargs)
         else:
             if index < self.len_trotter_steps-1:
                 overlap *= self.psi_t.compress(**self.state_compression_kwargs_noc)
             else:
                 if self.canonicalize_last_step:
                     overlap *= self.psi_t.compress(**self.state_compression_kwargs)
                 else:
                     overlap *= self.psi_t.compress(**self.state_compression_kwargs_noc)
         self.pmps_compression_step += 1
         if self.pmps_compression_step == self.compress_sites_step:
             compress_pmps_sites(self.psi_t, relerr=self.compress_sites_relerr, rank=self.compress_sites_rank,
                                 stable=self.compress_sites_stable, to_cform=self.to_cform)
             self.pmps_compression_step = 0
     self._normalize_state()
     self.cumulative_overlap *= overlap
     self.last_overlap = overlap
     self.trotter_error += self.propagator.step_trotter_error
     self.stepno += 1
コード例 #2
0
ファイル: tmps.py プロジェクト: gharib85/py-tmps
 def evolve(self):
     """
         Perform a Trotterized time evolution step by tau. Compress after each dot product or after each sweep
         through the chain. Renormalizes state after one full timestep due to compression.
     :return:
     """
     overlap = self.base_overlap
     last_start_at = self.system_index
     if not self.canonicalize_every_step:
         canonicalize_to(self.psi_t, to_cform=self.to_cform)
     for (start_at, trotter_mpo) in self.propagator.trotter_steps:
         self.psi_t = mp.partialdot(trotter_mpo,
                                    self.psi_t,
                                    start_at=start_at,
                                    axes=self.axes)
         if self.full_compression:
             if start_at == self.propagator.L - 2 or start_at == 0:
                 # Compress after a full sweep
                 if start_at != last_start_at:
                     overlap *= self.psi_t.compress(
                         **self.state_compression_kwargs)
         else:
             if len(trotter_mpo) > 1:
                 self.lc.compress(self.psi_t, start_at)
     if self.final_compression:
         overlap *= self.psi_t.compress(**self.state_compression_kwargs)
     else:
         if not self.canonicalize_every_step:
             canonicalize_to(self.psi_t, to_cform=self.to_cform)
     self._normalize_state()
     self.cumulative_overlap *= overlap
     self.last_overlap = overlap
     self.trotter_error += self.propagator.step_trotter_error
     self.stepno += 1
コード例 #3
0
    def reset(self, psi_0=None, state_compression_kwargs=None, psi_0_compression_kwargs=None):
        """
            Resets selected properties of the TPMPS object

            If psi_0 is not None, we set the new initial state to psi_0, otherwise we keep the current state.
            If psi_0 is to be changed, we reset overlap and trotter error tracking, thus it
            is advisable to check the info object before the reset in this case.
            Checks if shape of passed psi_0 is compatible with the shape of the current propagator object

        :param psi_0: Optional new initial state, need not be normalized. Is normalized before propagation
        :param state_compression_kwargs: Optional. If not None, chamge the current parameters for
                                         state compression. If set None old compression parameters are kept,
                                         if empty, default compression is used. (see real time evolution
                                         factory function for details)
        :param psi_0_compression_kwargs: Optional compresion kwargs for the initial state (see real time evolution
                                         factory function for details)
        :return:
        """
        if psi_0 is not None:
            if psi_0_compression_kwargs is None:
                canonicalize_to(psi_0, to_cform=self.to_cform)
            else:
                compress_pmps(psi_0, to_cform=self.to_cform, **psi_0_compression_kwargs)
            # Normalize current initial psi_t (=psi_0)
            self.normalize_state()
            self.pmps_compression_step = 0
            self.last_overlap = 1
            self.cumulative_overlap = 1
            self.base_overlap = 1
            self.trotter_error = 0
            self.start = True
            self.stepno = 0
        super().reset(psi_0=psi_0, state_compression_kwargs=state_compression_kwargs)
コード例 #4
0
 def _canonicalize(self, propagators):
     """
         Canonicalizes trotter operators (depending on to_cform)
     :param propagators: full trotter operators
     """
     for key, prop in propagators.items():
         canonicalize_to(prop, to_cform=self.to_cform)
コード例 #5
0
 def fast_evolve(self, end=True):
     """
         Perform a Trotterized time evolution step by tau. Compress after each dot product. Renormalizes state after
         one full Trotter-step due to compression.
         Without setting the end flag, the evolution does not do a complete trotter step, and the resulting state is
         therefore not immediately useable. Not setting the end flag allows for leaving out some unnecessary
         double steps and can therefore be used for propagating intermediate steps
     :parameter end: Flag, which can be set to false, if the current propagation only needs to produce an
                     intermediate step, which is not used otherwise.
     :return:
     """
     self.last_state_norm = self.curr_state_norm
     if self.start and end:
         trotter_steps = self.propagator.trotter_steps
     elif self.start and not end:
         trotter_steps = self.propagator.start_trotter_steps
         self.start = False
     elif not self.start and end:
         trotter_steps = self.propagator.end_trotter_steps
         self.start = True
     else:
         trotter_steps = self.propagator.step_trotter_steps
     if not self.canonicalize_every_step:
         canonicalize_to(self.psi_t, to_cform=self.to_cform)
     for index, (trotter_ui, trotter_ui_adj) in enumerate(trotter_steps):
         self.psi_t = mp.dot(trotter_ui, self.psi_t, self.axes)
         if self.canonicalize_every_step:
             self.psi_t.compress(**self.state_compression_kwargs)
         else:
             if index < self.len_trotter_steps - 1:
                 self.psi_t.compress(**self.state_compression_kwargs_noc)
             else:
                 if self.canonicalize_last_step:
                     self.psi_t.compress(**self.state_compression_kwargs)
                 else:
                     self.psi_t.compress(
                         **self.state_compression_kwargs_noc)
         self.psi_t = mp.dot(self.psi_t, trotter_ui.adj(), self.axes)
         if self.canonicalize_every_step:
             self.psi_t.compress(**self.state_compression_kwargs)
         else:
             if index < self.len_trotter_steps - 1:
                 self.psi_t.compress(**self.state_compression_kwargs_noc)
             else:
                 if self.canonicalize_last_step:
                     self.psi_t.compress(**self.state_compression_kwargs)
                 else:
                     self.psi_t.compress(
                         **self.state_compression_kwargs_noc)
     self._normalize_state()
     self.curr_state_norm = mp.norm(self.psi_t)
     self.trotter_error += 2 * self.propagator.step_trotter_error
     self.stepno += 1
     if self.start and not end:
         self.start = False
     elif not self.start and end:
         self.start = True
コード例 #6
0
    def __init__(self,
                 psi_0,
                 propagator,
                 state_compression_kwargs=None,
                 t0=0,
                 psi_0_compression_kwargs=None):
        """
            Constructor for the StarTMPO class. Time evolution for quantum states represented by mpo for a
            star geometry. Does required setup steps for evolve to work.
            Uses a pre-constructed MPPropagator object

        :param psi_0: Initial state as MPArray. More precisely as an MPArray with two physical legs on each site,
                      which have the same dimension (axis 0 = axis 1). Will be normalized before propagation
        :param propagator: Pre-constructed compatible StarMPPropagator object. (Compatibility means, that the
                           chain shape with which it was constructed matches the shape of psi_0 and that
                           it was constructed without ancilla sites, but with pre-calculated adjoints)
        :param state_compression_kwargs: Optional compression kwargs for the state (see real time evolution
                                         factory function for details)
        :param t0: Initial time of the propagation
        :param psi_0_compression_kwargs: Optional compression kwargs for the initial state (see real time evolution
                                         factory function for details)
        """
        super().__init__(psi_0,
                         propagator,
                         state_compression_kwargs=state_compression_kwargs,
                         t0=t0)
        self.mpa_type = 'mpo'
        self.system_index = propagator.system_index

        # Check if propagator is valid for the selected state mpa_type
        assert not self.propagator.ancilla_sites
        assert self.propagator.build_adj
        self.axes = (-1, 0)

        self.to_cform = propagator.to_cform

        if psi_0_compression_kwargs is None:
            canonicalize_to(self.psi_t, to_cform=self.to_cform)
        else:
            compress_mpa(self.psi_t,
                         to_cform=self.to_cform,
                         **psi_0_compression_kwargs)

        # trace normalize current initial psi_t (=psi_0)
        self.normalize_state()

        # If we deal with an mpo state we want to track the L2-norm of the state.
        # It should be approximately conserved by the trotterized evolution assuming no significant compression losses.
        self.init_state_norm = mp.norm(psi_0)
        self.last_state_norm = self.init_state_norm
        self.curr_state_norm = self.init_state_norm

        # Contains accumulated trotter errors for each timestep
        self.trotter_error = 0
コード例 #7
0
 def _compress_mpo(self, mpo):
     """
         Compresses and optionall canonicalizes a propagator mpo
     :param mpo:
     :return:
     """
     if self.op_compression_kwargs is not None:
         mpo.compress(**self.op_compression_kwargs)
         canonicalize_to(mpo, to_cform=self.to_cform)
         return mpo
     else:
         return mpo
コード例 #8
0
    def __init__(self,
                 psi_0,
                 propagator,
                 state_compression_kwargs=None,
                 t0=0,
                 psi_0_compression_kwargs=None):
        """
            Constructor for the StarTPMPS class. Time evolution for quantum states represented by purified state (pmps).
            Does required setup steps for evolve to work.
            Uses a pre-constructed MPPropagator object

        :param psi_0: Initial state as MPArray. More precisely as an MPArray with two legs on each site,
                      one physical, one ancilla. Will be normalized before propagation
        :param propagator: Compatible Pre-constructed StarMPPropagator object. (Compatibility means, that the
                           chain shape with which it was constructed matches the shape of psi_0)
        :param state_compression_kwargs: Optional compression kwargs for the state (see real time evolution
                                         factory function for details)
        :param t0: Initial time of the propagation
        :param psi_0_compression_kwargs: Optional compresion kwargs for the initial state (see real time evolution
                                         factory function for details)
        """
        super().__init__(psi_0,
                         propagator,
                         state_compression_kwargs=state_compression_kwargs,
                         t0=t0)
        self.mpa_type = 'pmps'
        self.system_index = propagator.system_index
        self.pmps_compression_step = 1

        # Check if propagator is valid for the selected state mpa_type
        assert self.propagator.ancilla_sites
        assert not self.propagator.build_adj
        # Contract over all indices (physical and ancilla)
        self.axes = ((1, 3), (0, 1))

        self.to_cform = propagator.to_cform
        if psi_0_compression_kwargs is None:
            canonicalize_to(self.psi_t, to_cform=self.to_cform)
        else:
            compress_pmps(self.psi_t,
                          to_cform=self.to_cform,
                          **psi_0_compression_kwargs)

        # Normalize current initial psi_t (=psi_0)
        self.normalize_state()

        # Contains overlap due to compression for the last timestep and for all timesteps combined respectively
        self.last_overlap = 1
        self.cumulative_overlap = 1
        self.base_overlap = 1

        # Contains accumulated trotter errors for each timestep
        self.trotter_error = 0
コード例 #9
0
ファイル: tmps.py プロジェクト: gharib85/py-tmps
    def __init__(self, psi_0, propagator, state_compression_kwargs=None, t0=0, psi_0_compression_kwargs=None):
        """
            Constructor for the TMPS class. Time evolution for quantum states represented by mps.
            Does required setup steps for evolve to work.
            Uses a pre-constructed MPPropagator object

        :param psi_0: Initial state as MPArray. More precisely as an MPArray with one physical leg on each site.
                      Will be normalized before propagation
        :param propagator: Compatible Pre-constructed MPPropagator object. (Compatibility means, that the
                           chain shape with which it was constructed matches the shape of psi_0)
        :param state_compression_kwargs: Optional compression kwargs for the state (see real time evolution
                                         factory function for details)
        :param t0: Initial time of the propagation
        :param psi_0_compression_kwargs: Optional compresion kwargs for the initial state (see real time evolution
                                         factory function for details)
        """
        super().__init__(psi_0, propagator, state_compression_kwargs=state_compression_kwargs, t0=t0,
                         psi_0_compression_kwargs=psi_0_compression_kwargs)
        self.mpa_type = 'mps'
        # Check if propagator is valid for the selected state mpa_type
        assert not self.propagator.ancilla_sites
        assert not self.propagator.build_adj

        self.axes = (-1, 0)

        self.to_cform = propagator.to_cform

        if psi_0_compression_kwargs is None:
            canonicalize_to(self.psi_t, to_cform=self.to_cform)
        else:
            compress_mpa(self.psi_t, to_cform=self.to_cform, **psi_0_compression_kwargs)

        # Normalize current initial psi_t (=psi_0)
        self.normalize_state()

        # Contains overlap due to compression for the last timestep and for all timesteps combined respectively
        self.last_overlap = 1
        self.cumulative_overlap = 1
        self.base_overlap = 1

        self.len_trotter_steps = len(self.propagator.trotter_steps)
        self.len_start_trotter_steps = len(self.propagator.start_trotter_steps)
        self.len_step_trotter_steps = len(self.propagator.step_trotter_steps)
        self.len_end_trotter_steps = len(self.propagator.end_trotter_steps)

        # Contains accumulated trotter errors for each timestep
        self.trotter_error = 0

        # Flag for the fast_evolve propagation type:
        self.start = True
コード例 #10
0
 def evolve(self):
     """
         Perform a Trotterized time evolution step by tau. Compress after each dot product or after each sweep
         through the chain. Renormalize state after one full timestep due to compression.
     :return:
     """
     overlap = self.base_overlap
     last_start_at = self.system_index
     if not self.canonicalize_every_step:
         canonicalize_to(self.psi_t, to_cform=self.to_cform)
     for (start_at, trotter_mpo) in self.propagator.trotter_steps:
         self.psi_t = mp.partialdot(trotter_mpo,
                                    self.psi_t,
                                    start_at=start_at,
                                    axes=self.axes)
         if self.full_compression:
             if (start_at == self.propagator.L - 2
                     or start_at == 0) and start_at != last_start_at:
                 # Compress after a full sweep
                 overlap *= self.psi_t.compress(
                     **self.state_compression_kwargs)
         else:
             if len(trotter_mpo) > 1:
                 self.lc.compress(self.psi_t, start_at)
         if (start_at == self.propagator.L - 2
                 or start_at == 0) and start_at != last_start_at:
             self.pmps_compression_step += 1
             if self.pmps_compression_step - 1 == self.compress_sites_step:
                 compress_pmps_sites(self.psi_t,
                                     relerr=self.compress_sites_relerr,
                                     rank=self.compress_sites_rank,
                                     stable=self.compress_sites_stable,
                                     to_cform=self.to_cform)
                 self.pmps_compression_step = 1
         last_start_at = start_at
     if self.final_compression:
         overlap *= self.psi_t.compress(**self.state_compression_kwargs)
     else:
         if not self.canonicalize_every_step:
             canonicalize_to(self.psi_t, to_cform=self.to_cform)
     self._normalize_state()
     self.cumulative_overlap *= overlap
     self.last_overlap = overlap
     if self.system_index == 0:
         # reset by one, because next propagation step starts at the edge of chain and increments counter immediately
         self.pmps_compression_step -= 1
     self.trotter_error += self.propagator.step_trotter_error
     self.stepno += 1
コード例 #11
0
def compress_pmps_sites(pmps,
                        relerr=1e-10,
                        rank=None,
                        stable=False,
                        to_cform=None):
    """
        Compresses pmps local sites
    :param pmps: MPArray (of pmps form)
    :param relerr: relative error for the compression
    :param rank: maximum rank of the compressed state
    :param to_cform: target canonical form ('left', 'right' or None)
    :param stable: If the stable but slower variant of the svd compression should be used directly instead of trying the
                   possibly faster one first
    """
    for site, lt in enumerate(pmps._lt):
        new_lt = _compressed_lt(lt, relerr, rank, stable)
        pmps._lt.update(site, new_lt, canonicalization=None)
    canonicalize_to(pmps, to_cform=to_cform)
コード例 #12
0
ファイル: thermal.py プロジェクト: gharib85/py-tmps
def get_thermal_state(beta,
                      h_site,
                      mpa_type='mpo',
                      as_type='mparray',
                      to_cform=None):
    """
        Generates a thermal state e^(-beta*H_i)/Z in pmps form or mpo form site local Hamiltonians (H_i) without
        couplings.
    :param beta: Inverse temperature
    :param h_site: local operator(s) of Hamiltonian as single numpy array or iterable of numpy arrays for each site.
                   If passed as 2d arrays, they are treated as full matrices. If they are passed as
                   vectors, they are treated as diagonal elements of a matrix
    :param mpa_type: Type of mpa to evolve (allowed are 'pmps' and 'mpo')
    :param as_type: 'mparray' means as one combined mparray.
                    'mparray_list' as list of individual mparrays in the same order as the h_site were passed
                    'ndarray' returns the states as a list of ndarrays in the same order as the h_site were passed
    :param to_cform: Desired canonical form of the mparray (if as_type was selected to be 'mparray')
    :return: thermal state in pmps or mpo form (Any ancilla sites have the same dimension as the physical ones),
             info object from the propagation (if beta was set 0 it returns an empty dict)
    """
    assert mpa_type == 'mpo' or mpa_type == 'pmps'
    thermal_states = []
    if isinstance(h_site, np.ndarray):
        if len(h_site.shape) == 2:
            if not isdiag(h_site):
                state = expm(-beta * h_site)
            else:
                state = np.diag(np.exp(-beta * np.diag(h_site)))
        elif len(h_site.shape) == 1:
            state = np.diag(np.exp(-beta * h_site))
        else:
            raise AssertionError(
                'Passed numpy array must either be of matrix or vector shape')
        thermal_states.append(state)
    else:
        try:
            for site in h_site:
                if len(site.shape) == 2:
                    if not isdiag(site):
                        state = expm(-beta * site)
                        thermal_states.append(state / np.trace(state))
                    else:
                        state = np.diag(np.exp(-beta * np.diag(site)))
                        thermal_states.append(state / np.trace(state))
                elif len(site.shape) == 1:
                    state = np.diag(np.exp(-beta * site))
                    thermal_states.append(state / np.trace(state))
                else:
                    raise AssertionError(
                        'Passed numpy array(s) must either be of matrix or vector shape'
                    )
        except TypeError:
            raise AssertionError(
                'h_site must be single numpy array or iterable of numpy arrays'
            )
    if as_type == 'ndarray':
        return thermal_states
    elif as_type == 'mparray':
        if mpa_type == 'pmps':
            state = mp.chain(purify_states(thermal_states, to='mparray'))
        elif mpa_type == 'mpo':
            state = mp.chain([
                mp.MPArray.from_array_global(state, ndims=2)
                for state in thermal_states
            ])
        else:
            raise AssertionError('Invalid mpa_type')
        canonicalize_to(state, to_cform=to_cform)
        return state
    elif as_type == 'mparray_list':
        if mpa_type == 'pmps':
            return purify_states(thermal_states, to='mparray')
        elif mpa_type == 'mpo':
            return [
                mp.MPArray.from_array_global(state, ndims=2)
                for state in thermal_states
            ]
        else:
            raise AssertionError('Invalid mpa_type')
    else:
        raise AssertionError('Unrecognized return type')