示例#1
0
def _hamiltonian_rdot(M, other):
	new = other.copy() #deep=False: not implememnted in hamiltonian_core.copy()
	new._dtype = _np.result_type(M.dtype,new._dtype)
	new._static = _expm_multiply(M, other.static)
	new._dynamic = {func:_expm_multiply(M, Hd) for func,Hd in iteritems(other._dynamic)}

	return new
示例#2
0
def _hamiltonian_dot(M, other):
    new = other.copy(deep=False)
    new._dtype = _np.result_type(M.dtype, new._dtype)
    new._static = _expm_multiply(M, other.static)
    new._dynamic = {
        func: _expm_multiply(M, Hd)
        for func, Hd in iteritems(other._dynamic)
    }

    return new
示例#3
0
def _iter_rdot(M, other, step, grid):
    if grid[0] != 0:
        M *= grid[0]
        other = _expm_multiply(M, other)
        M /= grid[0]

    yield other.T.copy()

    M *= step
    for t in grid[1:]:
        other = _expm_multiply(M, other)
        yield other.T.copy()
示例#4
0
def _expm_gen(psi, H, times, dt):
    """Generating function for evolution via `_expm_multiply`."""
    if times[0] != 0:
        H *= times[0]
        psi = _expm_multiply(H, psi)
        H /= times[0]

    yield psi

    H *= dt
    for t in times[1:]:
        psi = _expm_multiply(H, psi)
        yield psi
    H /= dt
示例#5
0
def _iter_sandwich(M, other, step, grid):
    if grid[0] != 0:
        M *= grid[0]
        other = _expm_multiply(M, other)
        other = _expm_multiply(M, other.T.conj()).T.conj()
        M /= grid[0]

    yield other.copy()

    M *= step
    for t in grid[1:]:
        other = _expm_multiply(M, other)
        other = _expm_multiply(M, other.T.conj()).T.conj()

        yield other.copy()
示例#6
0
    def rdot(self, other, shift=None, **call_kwargs):
        """Right-multiply an operator by matrix exponential.

		Let the matrix exponential object be :math:`\\exp(\\mathcal{O})` and let the operator be :math:`A`.
		Then this funcion implements:

		.. math::
			A \\exp(\\mathcal{O})

		Notes
		-----
		For `hamiltonian` objects `A`, this function is the same as `A.dot(expO)`.

		Parameters
		-----------
		other : obj
			The operator :math:`A` which multiplies from the left the matrix exponential :math:`\\exp(\\mathcal{O})`.
		shift : scalar
			Shifts operator to be exponentiated by a constant `shift` times the identity matrix: :math:`\\exp(\\mathcal{O} - \\mathrm{shift}\\times\\mathrm{Id})`.
		call_kwargs : obj, optional
			extra keyword arguments which include:
				**time** (*scalar*) - if the operator `O` to be exponentiated is a `hamiltonian` object.
				**pars** (*dict*) - if the operator `O` to be exponentiated is a `quantum_operator` object.
		
		Returns
		--------
		obj
			matrix exponential multiplied by `other` from the left.

		Examples
		---------
		>>> expO = exp_op(O)
		>>> A = exp_op(O,a=2j).get_mat()
		>>> print(expO.rdot(A))
		>>> print(A.dot(expO))
		
		"""

        is_sp = False
        is_ham = False

        if hamiltonian_core.ishamiltonian(other):
            shape = other._shape
            is_ham = True
        elif _sp.issparse(other):
            shape = other.shape
            is_sp = True
        elif other.__class__ in [_np.matrix, _np.ndarray]:
            shape = other.shape
        else:
            other = _np.asanyarray(other)
            shape = other.shape

        if other.ndim not in [1, 2]:
            raise ValueError(
                "Expecting a 1 or 2 dimensional array for 'other'")

        if other.ndim == 2:
            if shape[1] != self.get_shape[0]:
                raise ValueError(
                    "Dimension mismatch between expO: {0} and other: {1}".
                    format(self._O.get_shape, other.shape))
        elif shape[0] != self.get_shape[0]:
            raise ValueError(
                "Dimension mismatch between expO: {0} and other: {1}".format(
                    self._O.get_shape, other.shape))

        if shift is not None:
            M = (self._a *
                 (self.O(**call_kwargs) +
                  shift * _sp.identity(self.Ns, dtype=self.O.dtype))).T
        else:
            M = (self._a * self.O(**call_kwargs)).T

        if self._iterate:
            if is_ham:
                return _hamiltonian_iter_rdot(M, other.T, self._step,
                                              self._grid)
            else:
                return _iter_rdot(M, other.T, self._step, self._grid)
        else:
            if self._grid is None and self._step is None:

                if is_ham:
                    return _hamiltonian_rdot(M, other.T).T
                else:
                    return _expm_multiply(M, other.T).T
            else:
                if is_sp:
                    mats = _iter_rdot(M, other.T, self._step, self._grid)
                    return _np.array([mat for mat in mats])
                elif is_ham:
                    mats = _hamiltonian_iter_rdot(M, other.T, self._step,
                                                  self._grid)
                    return _np.array([mat for mat in mats])
                else:
                    ver = [int(v) for v in scipy.__version__.split(".")]
                    if _np.iscomplexobj(_np.float32(1.0).astype(
                            M.dtype)) and ver[1] < 19:
                        mats = _iter_rdot(M, other.T, self._step, self._grid)
                        return _np.array([mat for mat in mats])
                    else:
                        if other.ndim > 1:
                            return _expm_multiply(
                                M,
                                other.T,
                                start=self._start,
                                stop=self._stop,
                                num=self._num,
                                endpoint=self._endpoint).transpose(0, 2, 1)
                        else:
                            return _expm_multiply(M,
                                                  other.T,
                                                  start=self._start,
                                                  stop=self._stop,
                                                  num=self._num,
                                                  endpoint=self._endpoint)