def test_encode(self):
        # xxxxxxxxxx test the case with Ntx=2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        Nt = 2
        Nr = 2
        data = np.r_[0:15*Nt]

        channel = randn_c(Nr, Nt)
        self.gmdmimo_object.set_channel_matrix(channel)

        encoded_data = self.gmdmimo_object.encode(data)

        # data_aux = data.reshape(Nt, -1)
        U, S, V_H = np.linalg.svd(channel)
        _, _, P = gmd(U, S, V_H)
        W = P / math.sqrt(Nt)

        expected_encoded_data = W.dot(data.reshape(Nr, -1))
        np.testing.assert_array_almost_equal(
            expected_encoded_data, encoded_data)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Test if an exception is raised for wrong size xxxxxxxxxxxxx
        # The exception is raised if the input array size is not a multiple
        # of the number of transmit antennas
        data2 = np.r_[0:15*Nt+1]
        with self.assertRaises(ValueError):
            self.gmdmimo_object.encode(data2)
Exemple #2
0
    def _calc_precoder(channel):
        """
        Calculate the linear precoder for the MRT scheme.

        The MRT scheme corresponds to multiplying the symbol from each
        transmit antenna with a complex number corresponding to the inverse
        of the phase of the channel so as to ensure that the signals add
        constructively at the receiver. This also means that the MRT scheme
        only be applied to scenarios with a single receive antenna.

        Parameters
        ----------
        channel : np.ndarray
            MIMO channel matrix with dimension (1, Nt).

        Returns
        -------
        W : np.ndarray
            The precoder that can be applied to the input data.
        """
        Nt = channel.shape[1]
        # The encode method will precode the transmit_data using the
        # matrix 'P' obtained from the gmd.
        U, S, V_H = np.linalg.svd(channel)
        _, _, P = gmd(U, S, V_H)
        W = P / math.sqrt(Nt)
        return W
Exemple #3
0
    def _calc_precoder(channel):
        """
        Calculate the linear precoder for the MRT scheme.

        The MRT scheme corresponds to multiplying the symbol from each
        transmit antenna with a complex number corresponding to the inverse
        of the phase of the channel so as to ensure that the signals add
        constructively at the receiver. This also means that the MRT echeme
        only be applied to senarios with a single receive antenna.

        Parameters
        ----------
        channel : 2D numpy array
            MIMO channel matrix with dimention (1, Nt).

        Returns
        -------
        W : 2D numpy array
            The precoder that can be aplied to the input data.
        """
        Nt = channel.shape[1]
        # The encode method will precode the transmit_data using the
        # matrix 'P' obtained from the gmd.
        U, S, V_H = np.linalg.svd(channel)
        _, _, P = gmd(U, S, V_H)
        W = P / math.sqrt(Nt)
        return W
    def test_gmd(self):
        A = np.array([[6, 8, 0, 4],
                      [8, 6, 7, 6],
                      [10, 9, 7, 3],
                      [6, 2, 9, 2]])

        [U, S, V_H] = np.linalg.svd(A)
        # Store the SVD so that we can test later that gmd did not change
        # the input parameters
        U2 = U.copy()
        S2 = S.copy()
        V_H2 = V_H.copy()

        tol = 1e-6
        Q, R, P = misc.gmd(U, S, V_H, tol)

        # xxxxxxxxxx Test if the input parameters were changed xxxxxxxxxxxx
        np.testing.assert_array_almost_equal(U, U2)
        np.testing.assert_array_almost_equal(S, S2)
        np.testing.assert_array_almost_equal(V_H, V_H2)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if Q and P are unitary xxxxxxxxxxxxxxxxxxxxxxxxxx
        np.testing.assert_almost_equal(np.eye(4), Q.dot(Q.conj().T))
        np.testing.assert_almost_equal(np.eye(4), Q.conj().T.dot(Q))

        np.testing.assert_almost_equal(np.eye(4), P.dot(P.conj().T))
        np.testing.assert_almost_equal(np.eye(4), P.conj().T.dot(P))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if R is an upper triangular matrix xxxxxxxxxxxxxx
        # Furthermore, all diagonal elements must be the geometric mean of
        # the singular values of 'A'
        lambda_bar = np.prod(S)**(1./4.)
        np.testing.assert_almost_equal(R.diagonal(), lambda_bar)

        for i in range(4):
            # Elements in the diagonal or above it are not equal to zero
            for j in range(i, 4):
                self.assertNotAlmostEqual(0.0, R[i, j])

            # Elemetns below the diagonal are equal to zero
            for j in range(i):
                self.assertAlmostEqual(0.0, R[i, j])
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if the decomposition is right xxxxxxxxxxxxxxxxxxx
        np.testing.assert_almost_equal(A, Q.dot(R).dot(P.conj().T))
Exemple #5
0
    def test_gmd(self):
        A = np.array([[6, 8, 0, 4], [8, 6, 7, 6], [10, 9, 7, 3], [6, 2, 9, 2]])

        [U, S, V_H] = np.linalg.svd(A)
        # Store the SVD so that we can test later that gmd did not change
        # the input parameters
        U2 = U.copy()
        S2 = S.copy()
        V_H2 = V_H.copy()

        tol = 1e-6
        Q, R, P = misc.gmd(U, S, V_H, tol)

        # xxxxxxxxxx Test if the input parameters were changed xxxxxxxxxxxx
        np.testing.assert_array_almost_equal(U, U2)
        np.testing.assert_array_almost_equal(S, S2)
        np.testing.assert_array_almost_equal(V_H, V_H2)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if Q and P are unitary xxxxxxxxxxxxxxxxxxxxxxxxxx
        np.testing.assert_almost_equal(np.eye(4), Q.dot(Q.conj().T))
        np.testing.assert_almost_equal(np.eye(4), Q.conj().T.dot(Q))

        np.testing.assert_almost_equal(np.eye(4), P.dot(P.conj().T))
        np.testing.assert_almost_equal(np.eye(4), P.conj().T.dot(P))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if R is an upper triangular matrix xxxxxxxxxxxxxx
        # Furthermore, all diagonal elements must be the geometric mean of
        # the singular values of 'A'
        lambda_bar = np.prod(S)**(1. / 4.)
        np.testing.assert_almost_equal(R.diagonal(), lambda_bar)

        for i in range(4):
            # Elements in the diagonal or above it are not equal to zero
            for j in range(i, 4):
                self.assertNotAlmostEqual(0.0, R[i, j])

            # Elements below the diagonal are equal to zero
            for j in range(i):
                self.assertAlmostEqual(0.0, R[i, j])
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Test if the decomposition is right xxxxxxxxxxxxxxxxxxx
        np.testing.assert_almost_equal(A, Q.dot(R).dot(P.conj().T))
Exemple #6
0
    def _calc_precoder(channel: np.ndarray) -> np.ndarray:
        """
        Calculate the linear precoder for the GMD scheme.

        Parameters
        ----------
        channel : np.ndarray
            MIMO channel matrix with dimension (1, Nt).

        Returns
        -------
        W : np.ndarray
            The precoder that can be applied to the input data.
        """
        Nt = channel.shape[1]
        # The encode method will precode the transmit_data using the
        # matrix 'P' obtained from the gmd.
        U, S, V_H = np.linalg.svd(channel)
        _, _, P = gmd(U, S, V_H)
        W = P / math.sqrt(Nt)
        return W
Exemple #7
0
    def _calc_receive_filter(channel, noise_var=None):
        """
        Calculate the receive filter for the MRT scheme.

        Parameters
        ----------
        channel : np.ndarray
            MIMO channel matrix.
        noise_var : float
            The noise variance.

        Returns
        -------
        G_H : np.ndarray
            The receive_filter that can be applied to the input data.
        """
        U, S, V_H = np.linalg.svd(channel)
        Q, R, _ = gmd(U, S, V_H)
        channel_eq = Q.dot(R)

        # Use the _calc_receive_filter method from the base class (Blast)
        G_H = Blast._calc_receive_filter(channel_eq, noise_var)
        return G_H
Exemple #8
0
    def _calc_receive_filter(channel, noise_var=None):
        """
        Calculate the receive filter for the MRT scheme.

        Parameters
        ----------
        channel : 2D numpy array
            MIMO channel matrix.
        noise_var : float
            The noise variance.

        Returns
        -------
        G_H : 2D numpy array
            The receive_filter that can be aplied to the input data.
        """
        U, S, V_H = np.linalg.svd(channel)
        Q, R, _ = gmd(U, S, V_H)
        channel_eq = Q.dot(R)

        # Use the _calc_receive_filter method from the base class (Blast)
        G_H = Blast._calc_receive_filter(channel_eq, noise_var)
        return G_H