コード例 #1
0
def lindblad_superop_sum_element(l_op: np.ndarray) -> np.ndarray:
    """
    For a Lindbladian superoperator that is formed by summation
    over index \\alpha, this function constructs the Lindbladian
    superoperator for a particular value of this index from the
    corresponding Lindblad operator, A. This is given by:

    .. math::
        A^* \\otimes A - 0.5
        ((A^{\\dagger} A)^* \\otimes I + I \\otimes A^{\\dagger} A)

    Parameters
    ----------
    l_op : np.ndarray
        The Lindblad operator A for the given Lindblad model.

    Returns
    -------
    np.ndarray
        The N^2 x N^2 superoperator (where N x N is the dimension
        of the Lindblad operator) for the specific index at which
        the Lindblad operator has been constructed.
    """

    assert l_op.shape[0] == l_op.shape[1], 'Lindblad operator must be square.'

    l_op_dag = l_op.T.conjugate()
    iden = np.eye(l_op.shape[0])
    return (np.kron(l_op.conjugate(), l_op) - 0.5 *
            (np.kron(np.matmul(l_op_dag, l_op).conjugate(), iden) +
             np.kron(iden, np.matmul(l_op_dag, l_op))))
コード例 #2
0
def get_single_qubit_unitary(num_qubits: int, gate_unitary: np.ndarray,
                             target_qubit: int) -> np.ndarray:
    """Return single qubit unitary operator of size 2**n x 2**n for given gate and target qubits."""
    if target_qubit >= num_qubits:
        raise IndexError("Target qubit is outside of qubits array.")

    if np.shape(gate_unitary) != (2, 2):
        raise TypeError("Gate must be 2x2 array.")

    if not np.allclose(
            np.dot(gate_unitary,
                   gate_unitary.conjugate().transpose()), np.identity(2)):
        raise ValueError("Gate must be unitary.")

    # initialize the matrix
    gate = np.array([1])

    for i in range(num_qubits):
        if i == target_qubit:
            # target qubit, apply unitary
            gate = np.kron(gate, gate_unitary)
        else:
            # not target, apply identity
            gate = np.kron(gate, np.identity(2))

    return gate
コード例 #3
0
ファイル: utilities.py プロジェクト: xuanleng/quantum_HEOM
def basis_change(matrix: np.ndarray,
                 states: np.ndarray,
                 liouville: bool = False) -> np.ndarray:
    """
    Transforms a matrix expressed in Liouville space into the basis
    expressed by the states matrix.

    Parameters
    ----------
    matrix : np.ndarray
        The matrix to be transformed. If in Liouville space, must
        set 'liouville=True' and 'matrix' must have dimensions
        N^2 x N^2. Otherwise, pass in N x N dimensions.
    states : np.ndarray
        The Hilbert space of states in the basis into which
        'matrix' will be transformed, of dimensions N x N. 'states'
        must be orthogonal (i.e. that states^{dagger} states = I),
        and each column must correspond to an eigenstate.
    liouville : bool
        Whether or not the input matrix 'matrix' is given in
        Liouville space. If True, 'matrix' must be given in
        dimensions N^2 x N^2 and 'states' as N x N. If False
        (default), both 'matrix' and 'states' must be N x N.

    Returns
    -------
    np.ndarray
        The input matrix transformed. Has dimensions N^2 x N^2 if
        'matrix' passed in Liouville space, or N x N otherwise.
    """

    # Check 'matrix' and 'states' are square
    assert (matrix.shape[0] == matrix.shape[1] and states.shape[0]
            == states.shape[1]), ('Input matrices must be square.')
    assert isinstance(liouville, bool), 'Must pass liouville as a bool.'

    # Perform transformation
    if liouville:
        assert matrix.shape[0] == states.shape[0]**2, (
            'If providing an input matrix in Liouville space it must have'
            ' dimensions N^2 x N^2, where the eigenstates matrix has dimensions'
            ' N x N.')
        states = np.kron(states, states.conjugate())
    # Check for orthogonality
    # assert np.allclose(np.matmul(states, states.conjugate().T),
    #                    np.eye(matrix.shape[0]))
    return np.matmul(states, np.matmul(matrix, states.conjugate().T))
コード例 #4
0
def make_density_matrix_numpy(wf: ndarray):
    if wf.ndim == 1:
        return outer(wf, wf.conjugate())
    if wf.ndim == 2:
        wf_dim, num_wf = wf.shape
        ret = empty(shape=(num_wf, wf_dim, wf_dim), dtype=wf.dtype)
        for wf_idx in range(num_wf):
            a_wf = wf[:, wf_idx]
            ret[wf_idx, :, :] = outer(a_wf, a_wf.conjugate())
        return ret
    raise NotImplementedError(wf.shape)
コード例 #5
0
def is_unitary(matrix: np.ndarray) -> bool:
    """
    Check if the passed in matrix of size (n times n) is unitary.

    Arguments:
    matrix: the matrix which is checked

    Return:
    unitary: True if the matrix is unitary
    """

    mcon = matrix.conjugate().T
    return np.allclose(np.dot(mcon, matrix), np.identity(len(matrix)))
コード例 #6
0
def get_measurement_outcome(state: np.ndarray) -> str:
    """Return random outcome of measurement in computational basis."""
    if len(np.shape(state)) != 1:
        raise TypeError("State vector must be shape (n,).")

    if np.modf(np.log2(np.shape(state)[0]))[0] != 0:
        raise TypeError("Length of state vector must be power of 2.")

    if not np.allclose(np.inner(state.conjugate(), state), 1.):
        raise ValueError("State vector must be normalized.")

    # output probability distribution
    prob = np.real(np.multiply(state.conjugate(), state))
    # dimension of the Hilbert space
    dim = np.shape(state)[0]
    # number of qubits
    n = int(np.modf(np.log2(dim))[1])
    # tuple of all possible outcomes
    outcomes = tuple(range(dim))

    # random package used to sample the outcome of the measurement
    result = random.choices(outcomes, prob)[0]

    return bin(result)[2:].zfill(n)
コード例 #7
0
ファイル: tensor.py プロジェクト: yosefsadek/pyzx
def adjoint(t: np.ndarray) -> np.ndarray:
    """Returns the adjoint of the tensor as if it were representing
    a circuit::

        t = tensorfy(circ)
        tadj = tensorfy(circ.adjoint())
        compare_tensors(adjoint(t),tadj) # This is True

    """

    q = len(t.shape) // 2
    transp = []
    for i in range(q):
        transp.append(q + i)
    for i in range(q):
        transp.append(i)
    return np.transpose(t.conjugate(), transp)
コード例 #8
0
def is_hermitian(matrix: np.ndarray) -> bool:
    """
    Checks if a matrix is Hermitian.
    >>> import numpy as np
    >>> A = np.array([
    ... [2,    2+1j, 4],
    ... [2-1j,  3,  1j],
    ... [4,    -1j,  1]])
    >>> is_hermitian(A)
    True
    >>> A = np.array([
    ... [2,    2+1j, 4+1j],
    ... [2-1j,  3,  1j],
    ... [4,    -1j,  1]])
    >>> is_hermitian(A)
    False
    """
    return np.array_equal(matrix, matrix.conjugate().T)
コード例 #9
0
def inner_product(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    """
    Calculates the inner product between vectors a and b, which equals <a|b>.

    :param a:
        Vector of n-dimensional (n,), or some vectors of n-dimensional (m, n).
    :param b:
        Vector of n-dimensional (n,), or some vectors of n-dimensional (m, n).
    :return:
        Inner product between |a> and |b>.

    """
    braket_a_b = a.conjugate() * b
    if braket_a_b.ndim == 1:
        braket_a_b = sum(braket_a_b)
    else:
        braket_a_b = np.sum(braket_a_b, axis=1)
    return braket_a_b
コード例 #10
0
def rayleigh_quotient(A: np.ndarray, v: np.ndarray) -> Any:
    """
    Returns the Rayleigh quotient of a Hermitian matrix A and
    vector v.
    >>> import numpy as np
    >>> A = np.array([
    ... [1,  2, 4],
    ... [2,  3,  -1],
    ... [4, -1,  1]
    ... ])
    >>> v = np.array([
    ... [1],
    ... [2],
    ... [3]
    ... ])
    >>> rayleigh_quotient(A, v)
    array([[3.]])
    """
    v_star = v.conjugate().T
    v_star_dot = v_star.dot(A)
    assert isinstance(v_star_dot, np.ndarray)
    return (v_star_dot.dot(v)) / (v_star.dot(v))
コード例 #11
0
    def calcProjectionMatrix(A: np.ndarray) -> np.ndarray:
        """
        Calculates the projection matrix that projects a vector (or a
        matrix) into the signal space spanned by the columns of `A`.

        Parameters
        ----------
        A : np.ndarray
            A matrix whose columns form a basis for the desired subspace.

        Returns
        -------
        np.ndarray
            The projection matrix that can be used to project a vector or a
            matrix into the subspace spanned by the columns of `A`

        See also
        --------
        calcOrthogonalProjectionMatrix

        Examples
        --------
        >>> A = np.array([[1 + 1j, 2 - 2j], [3 - 2j, 0], \
                          [-1 - 1j, 2 - 3j]])
        >>> # Matrix that projects into the subspace spanned by the columns
        >>> # of A
        >>> Q = calcProjectionMatrix(A)
        >>> np.allclose(Q.round(4), np.array( \
          [[ 0.5239+0.j, 0.0366+0.3296j, 0.3662+0.0732j], \
           [ 0.0366-0.3296j, 0.7690+0.j, -0.0789+0.2479j], \
           [ 0.3662-0.0732j, -0.0789-0.2479j, 0.7070-0.j]]))
        True
        """
        # MATLAB version: A/(A'*A)*A';
        A_H = A.conjugate().transpose()
        return (A.dot(np.linalg.inv(A_H.dot(A)))).dot(A_H)
コード例 #12
0
def is_hermitian(A: np.ndarray) -> bool:
    return A == A.conjugate()
コード例 #13
0
def state_to_density_matrix(state: np.ndarray):
    return np.matmul(state, state.conjugate().transpose())
コード例 #14
0
 def dot(a: np.ndarray,
         b: np.ndarray,
         out: np.ndarray = None) -> np.ndarray:
     """calculate dot product with conjugated second operand"""
     return calc(a, b.conjugate(), out=out)  # type: ignore
コード例 #15
0
def inner_product(u: np.ndarray, v: np.ndarray) -> np.ndarray:
    return np.dot(u, v.conjugate())
コード例 #16
0
def fast_ambiguity(
    num_delay_bins: int,
    num_doppler_bins: int,
    reference_signal: np.ndarray,
    surveillance_signal: np.ndarray,
) -> np.ndarray:
    """Fast implementation of cross ambiguity function (CAF), using Fourier
    Transform of Lag Product approach.

    Parameters
    ----------
    num_delay_bins : int
        Number of delay bins by which to shift the surveillance signal in
        time-domain and calculate the CAF. Must be
        `>= 1`.
    num_doppler_bins : int
        Number of frequency bins by which to shift the surveillance signal in
        frequency-domain and calculate the CAF.
        Must be `>= 1`.
    reference_signal : np.ndarray
        Samples from the reference channel, which contains the direct path
        signal.
    surveillance_signal : np.ndarray
        Samples from the surveillance channel, which contains target echos.

    Returns
    -------
    np.ndarray
        Cross ambiguity of surveillance and reference signal as 2D array with
        size `num_delay_bins` x `num_doppler_bins`.

    Examples
    --------
    Calculate the CAF of a real-valued rectangular pulse shifted by 50 samples.
    This will produce a triangular CAF with its peak at the 50th element.
    >>> reference = np.pad(np.ones(10), (0, 1000))
    >>> surveillance = np.roll(reference, 50)
    >>> amb = fast_ambiguity(
    ...     num_delay_bins=100,
    ...     num_doppler_bins=1,
    ...     reference_signal=reference,
    ...     surveillance_signal=surveillance)
    >>> np.argmax(amb)
    50

    Comprehensive example in which an amplitude modulated square wave is shifted
    in time and frequency.
    >>> import matplotlib.pyplot as plt

    >>> duration = 1.0
    >>> duty_cycle = 0.5
    >>> delay = 0.3
    >>> doppler = -0.2
    >>> sample_rate = 4000
    >>> carrier_freq = 100
    >>> num_samples = int(duration * sample_rate)
    >>> t = np.arange(num_samples) / sample_rate

    >>> waveform_prototype = np.concatenate(
    ...     [
    ...         np.ones(int(num_samples * duty_cycle)),
    ...         np.zeros(int(num_samples * (1 - duty_cycle))),
    ...     ]
    ... )

    >>> waveform_prototype *= 1 + 0.5 * np.sin(2 * np.pi * carrier_freq * t)

    >>> waveform = scipy.signal.hilbert(waveform_prototype)

    >>> ref_waveform = waveform
    >>> surv_waveform = np.roll(
    ...     ref_waveform, int(delay * waveform.shape[0])
    ... ) * np.exp(-2j * doppler * np.pi * sample_rate * t)

    >>> _, axs = plt.subplots(2, 1, figsize=(10, 7))
    >>> _ = axs[0].plot(np.real(ref_waveform))
    >>> _ = axs[0].set_title("Reference Channel")
    >>> _ = axs[0].set_ylabel("Real");
    >>> axs[0].grid(True)
    >>> _ = axs[1].plot(np.real(surv_waveform));
    >>> _ = axs[1].set_title("Surveillance Channel");
    >>> _ = axs[1].set_ylabel("Real");
    >>> axs[1].grid(True)

    >>> amb = fast_ambiguity(
    ...     num_samples,
    ...     sample_rate,
    ...     ref_waveform,
    ...     surv_waveform
    ... )
    >>> peak = np.unravel_index(np.argmax(amb), amb.shape)

    >>> _, ax = plt.subplots(figsize=(10, 5))
    >>> _ = ax.set_title("Cross Ambiguity (log-scale)")
    >>> _ = ax.annotate(
    ...     f"Peak ({peak[0]},{peak[1] - sample_rate // 2:.0f})",
    ...     peak,
    ...     xytext=(10, 10),
    ...     xycoords="data",
    ...     textcoords="offset pixels",
    ...     arrowprops={"arrowstyle": "wedge"},
    ... )
    >>> _ = ax.set_xlabel("Delay [Samples]")
    >>> _ = ax.set_ylabel("Doppler [Hz]")
    >>> _ = ax.set_yticks(np.linspace(0, sample_rate, 8, endpoint=False))
    >>> _ = ax.set_yticklabels(
    ...     map(lambda y: f"{y - sample_rate // 2:.0f}", ax.get_yticks())
    ... )
    >>> _ = ax.imshow(10 * np.log10(np.abs(amb.T)))

    >>> assert np.allclose(
    ...     peak,
    ...     np.array(
    ...         [
    ...             num_samples * delay,
    ...             sample_rate * doppler + sample_rate // 2,
    ...         ]
    ...     ),
    ...     atol=200,
    ... )
    """
    num_samples_per_cpi = reference_signal.shape[0]

    num_taps = num_samples_per_cpi // num_doppler_bins

    fir = scipy.signal.dlti(np.ones(num_taps), 1)

    amb = np.empty((num_delay_bins, num_doppler_bins), dtype=np.complex64)

    surv_cmplx_conj = surveillance_signal.conjugate()
    surv_cmplx_conj = np.pad(surv_cmplx_conj, pad_width=(0, num_delay_bins))

    lag_product = np.empty((num_samples_per_cpi, ), dtype=amb.dtype)
    decimation = np.empty((num_doppler_bins, ), dtype=amb.dtype)
    for delay_bin, lag in enumerate(-np.arange(num_delay_bins)):
        np.multiply(
            reference_signal,
            np.roll(surv_cmplx_conj, lag)[:num_samples_per_cpi],
            out=lag_product,
        )
        decimation[:] = scipy.signal.decimate(lag_product, num_taps,
                                              ftype=fir)[:num_doppler_bins]
        amb[delay_bin, :] = decimation

    amb = scipy.fft.fftshift(scipy.fft.fft(amb, axis=1), axes=1)

    return amb
コード例 #17
0
    def gpu_ambiguity(
        num_delay_bins: int,
        num_doppler_bins: int,
        reference_signal: np.ndarray,
        surveillance_signal: np.ndarray,
        num_samples_per_cpi: int,
        batch_size: int = 1,
    ) -> np.ndarray:
        """Fast implementation of cross ambiguity function (CAF) on GPU, using
        Fourier Transform of Lag Product approach.

        Requires CuPy to be installed.

        Parameters
        ----------
        num_delay_bins : int
            Number of delay bins by which to shift the surveillance signal in
            time-domain and calculate the CAF. Must be `>= 1`.
        num_doppler_bins : int
            Number of frequency bins by which to shift the surveillance signal
            in frequency-domain and calculate the CAF. Must be `>= 1`.
        reference_signal : np.ndarray
            Samples from the reference channel, which contains the direct path
            signal.
        surveillance_signal : np.ndarray
            Samples from the surveillance channel, which contains target echos.
        num_samples_per_cpi : int
            Number of samples per Coherent Processing Intervall (CPI), i.e. how
            many samples shall be correlated.
        batch_size : Optional[int]
            Number of consecutive CPIs to be processed. Inputs
            `reference_signal` and `surveillance_signal` must contain at least
            `num_samples_per_cpi * batch_size` samples.

        Returns
        -------
        np.ndarray
            Cross ambiguity of surveillance and reference signal as 2D array
            with size `num_delay_bins` x `num_doppler_bins` x `batch_size`.

        Examples
        --------
        Calculate the CAF of a real-valued rectangular pulse shifted by 50
        samples.
        This will produce a triangular CAF with its peak at the 50th element.
        >>> reference = np.pad(np.ones(10), (0, 1000))
        >>> surveillance = np.roll(reference, 50)
        >>> amb = gpu_ambiguity(
        ...     num_delay_bins=100,
        ...     num_doppler_bins=1,
        ...     reference_signal=reference,
        ...     surveillance_signal=surveillance,
        ...     num_samples_per_cpi=reference.shape[0])
        >>> np.argmax(amb)
        50
        """

        reference_signal = cp.asarray(
            reference_signal[:num_samples_per_cpi * batch_size].reshape(
                num_samples_per_cpi, batch_size))
        surveillance_signal = cp.asarray(
            surveillance_signal[:num_samples_per_cpi * batch_size].reshape(
                num_samples_per_cpi, batch_size))

        num_taps = num_samples_per_cpi // num_doppler_bins

        amb = cp.empty(
            (num_delay_bins, num_doppler_bins, batch_size),
            dtype=cp.complex64,
        )

        surv_cmplx_conj = surveillance_signal.conjugate()
        surv_cmplx_conj = cp.pad(surv_cmplx_conj,
                                 pad_width=((0, num_delay_bins), (0, 0)))

        lag_product = cp.empty((num_samples_per_cpi, batch_size),
                               dtype=amb.dtype)
        decimation = cp.empty_like(lag_product)
        for delay_bin, lag in enumerate(-np.arange(num_delay_bins)):
            cp.multiply(
                reference_signal,
                cp.roll(surv_cmplx_conj, lag, axis=0)[:num_samples_per_cpi],
                out=lag_product,
            )

            decimation[:] = cusignal.decimate(lag_product, num_taps, axis=1)
            amb[delay_bin, :, :] = decimation[:num_doppler_bins, :]

        amb = cp.fft.fftshift(cp.fft.fft(amb, axis=1), axes=1)

        return amb.get()
コード例 #18
0
def dagger(vector: np.ndarray) -> np.ndarray:
    """Compute the hermitian conjugate of a vector or matrix"""
    return vector.conjugate().transpose()
コード例 #19
0
ファイル: tensorial.py プロジェクト: yiweizhang1025/py-pde
 def dot(a: np.ndarray,
         b: np.ndarray,
         out: np.ndarray = None) -> np.ndarray:
     return calc(a, b.conjugate(), out=out)  # type: ignore