Esempio n. 1
0
    def test_block_diagonalize_no_waterfilling(self):
        Nr = np.array([2, 2])
        Nt = np.array([2, 2])
        K = Nt.size
        Nti = 1
        iPu = 1e-1  # Power for each user (linear scale)
        pe = 1e-3  # External interference power (in linear scale)
        noise_var = 1e-4

        # # The modulator and packet_length are required in the
        # # effective_throughput metric case
        # psk_obj = modulators.PSK(4)
        # packet_length = 120

        multiUserChannel = multiuser.MultiUserChannelMatrixExtInt()
        multiUserChannel.randomize(Nr, Nt, K, Nti)

        # Channel from all transmitters to the first receiver
        H1 = multiUserChannel.get_Hk_without_ext_int(0)
        # Channel from all transmitters to the second receiver
        H2 = multiUserChannel.get_Hk_without_ext_int(1)

        # Create the whiteningBD object and the regular BD object
        whiteningBD_obj = blockdiagonalization.WhiteningBD(
            K, iPu, noise_var, pe)

        # noise_plus_int_cov_matrix \
        #     = multiUserChannel.calc_cov_matrix_extint_plus_noise(
        #         noise_var, pe)

        # xxxxx First we test without ext. int. handling xxxxxxxxxxxxxxxxxx
        (Ms_all, Wk_all, Ns_all) \
            = whiteningBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        Ms1 = Ms_all[0]
        Ms2 = Ms_all[1]

        self.assertEqual(Ms1.shape[1], Ns_all[0])
        self.assertEqual(Ms2.shape[1], Ns_all[1])

        # Most likely only one base station (the one with the worst
        # channel) will employ a precoder with total power of `Pu`,
        # while the other base stations will use less power.
        tol = 1e-10
        self.assertGreaterEqual(iPu + tol, np.linalg.norm(Ms1, 'fro')**2)
        # 1e-12 is included to avoid false test fails due to small
        # precision errors
        self.assertGreaterEqual(iPu + tol, np.linalg.norm(Ms2, 'fro')**2)

        # Test if the precoder block diagonalizes the channel
        self.assertNotAlmostEqual(np.linalg.norm(np.dot(H1, Ms1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, Ms2), 'fro'), 0)
        self.assertNotAlmostEqual(np.linalg.norm(np.dot(H2, Ms2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, Ms1), 'fro'), 0)
Esempio n. 2
0
    def test_calc_whitening_matrices(self):
        Nr = np.array([2, 2])
        Nt = np.array([2, 2])
        K = Nt.size
        Nti = 1
        iPu = 1e-1  # Power for each user (linear scale)
        pe = 1e-3  # External interference power (in linear scale)
        noise_var = 1e-4

        # Generate the multi-user channel
        mu_channel = multiuser.MultiUserChannelMatrixExtInt()
        mu_channel.randomize(Nr, Nt, K, Nti)
        mu_channel.noise_var = noise_var

        bd_obj = blockdiagonalization.BDWithExtIntBase(K, iPu, noise_var, pe)
        W_all_k = bd_obj.calc_whitening_matrices(mu_channel)

        R_all_k = mu_channel.calc_cov_matrix_extint_plus_noise(pe)
        for W, R in zip(W_all_k, R_all_k):
            np.testing.assert_array_almost_equal(
                W,
                calc_whitening_matrix(R).conjugate().T)
Esempio n. 3
0
    def __init__(self, read_command_line_args=True, save_parsed_file=False):
        default_config_file = 'bd_config_file.txt'

        # xxxxxxxxxx Simulation Parameters Specification xxxxxxxxxxxxxxxxxx
        spec = """[Grid]
        cell_radius=float(min=0.01, default=1.0)
        num_cells=integer(min=3,default=3)
        num_clusters=integer(min=1,default=1)

        [Scenario]
        NSymbs=integer(min=10, max=1000000, default=500)
        SNR=real_numpy_array(min=-50, max=100, default=0:3:31)
        Pe_dBm=real_numpy_array(min=-50, max=100, default=[-10. 0. 10.])
        Nr=integer(default=2)
        Nt=integer(default=2)
        N0=float(default=-116.4)
        ext_int_rank=integer(min=1,default=1)
        user_positioning_method=option("Random", 'Symmetric Far Away', default="Symmetric Far Away")

        [Modulation]
        M=integer(min=4, max=512, default=4)
        modulator=option('QPSK', 'PSK', 'QAM', 'BPSK', default="PSK")
        packet_length=integer(min=1,default=60)

        [General]
        rep_max=integer(min=1, default=5000)
        unpacked_parameters=string_list(default=list('SNR','Pe_dBm'))

        """.split("\n")
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Initialize parameters configuration xxxxxxxxxxxxxxxxxx
        # Among other things, this will create the self.params object with
        # the simulation parameters read from the config file.
        SimulationRunner.__init__(
            self,
            default_config_file=default_config_file,
            config_spec=spec,
            read_command_line_args=read_command_line_args,
            save_parsed_file=save_parsed_file)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Channel Parameters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        self.path_loss_obj = pathloss.PathLoss3GPP1()
        self.multiuser_channel = multiuser.MultiUserChannelMatrixExtInt()
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx RandomState objects seeds xxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # This is only useful to reproduce a simulation for debugging
        # purposed
        channel_seed = None  # 22522
        self.noise_seed = None  # 4445
        self.data_gen_seed = np.random.randint(10000)  # 2105
        ext_data_gen_seed = None  # 6114
        #
        self.multiuser_channel.set_channel_seed(channel_seed)
        self.multiuser_channel.set_noise_seed(self.noise_seed)
        self.data_RS = np.random.RandomState(self.data_gen_seed)
        self.ext_data_RS = np.random.RandomState(ext_data_gen_seed)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Creates the modulator object xxxxxxxxxxxxxxxxxxxxxxxxx
        M = self.params['M']
        modulator_options = {
            'PSK': fundamental.PSK,
            'QPSK': fundamental.QPSK,
            'QAM': fundamental.QAM,
            'BPSK': fundamental.BPSK
        }
        self.modulator = modulator_options[self.params['modulator']](M)
        ":type: fundamental.PSK | fundamental.QPSK | fundamental.QAM | fundamental.BPSK"

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx General Parameters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # Maximum number of repetitions for each unpacked parameters set
        # self.params self.results
        self.rep_max = self.params['rep_max']

        # # max_bit_errors is used in the _keep_going method to stop the
        # # simulation earlier if possible. We stop the simulation if the
        # # accumulated number of bit errors becomes greater then 5% of the
        # # total number of simulated bits
        # self.max_bit_errors = self.rep_max * NSymbs * 5. / 100.

        self.progressbar_message = "SNR: {SNR}, Pe_dBm: {Pe_dBm}"

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # xxxxxxxxxx Dependent parameters (don't change these) xxxxxxxxxxxx
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # These two will be set in the _on_simulate_current_params_start
        # method
        self.pe = 0

        # Path loss (in linear scale) from the cell center to
        # self.path_loss_border = self.path_loss_obj.calc_path_loss(
        #     self.cell_radius)

        # Cell Grid
        self.cell_grid = cell.Grid()
        self.cell_grid.create_clusters(self.params['num_clusters'],
                                       self.params['num_cells'],
                                       self.params['cell_radius'])
        self.noise_var = dBm2Linear(self.params['N0'])
        self.multiuser_channel.noise_var = self.noise_var

        # This can be either 'screen' or 'file'. If it is 'file' then the
        # progressbar will write the progress to a file with appropriated
        # filename
        self.progress_output_type = 'screen'
Esempio n. 4
0
    def test_block_diagonalize_no_waterfilling(self):
        Nr = np.array([2, 2])
        Nt = np.array([2, 2])
        K = Nt.size
        Nti = 1
        iPu = 1e-1  # Power for each user (linear scale)
        pe = 1e-3  # External interference power (in linear scale)
        noise_var = 1e-1

        # The modulator and packet_length are required in the
        # effective_throughput metric case
        psk_obj = fundamental.PSK(4)
        packet_length = 120

        multiUserChannel = multiuser.MultiUserChannelMatrixExtInt()
        multiUserChannel.randomize(Nr, Nt, K, Nti)
        multiUserChannel.noise_var = noise_var

        # Channel from all transmitters to the first receiver
        H1 = multiUserChannel.get_Hk_without_ext_int(0)
        # Channel from all transmitters to the second receiver
        H2 = multiUserChannel.get_Hk_without_ext_int(1)

        # Create the enhancedBD object
        enhancedBD_obj = blockdiagonalization.EnhancedBD(K, iPu, noise_var, pe)

        noise_plus_int_cov_matrix \
            = multiUserChannel.calc_cov_matrix_extint_plus_noise(pe)

        # xxxxx First we test without ext. int. handling xxxxxxxxxxxxxxxxxx
        enhancedBD_obj.set_ext_int_handling_metric(None)
        (Ms_all, Wk_all, Ns_all) \
            = enhancedBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        Ms1 = Ms_all[0]
        Ms2 = Ms_all[1]

        self.assertEqual(Ms1.shape[1], Ns_all[0])
        self.assertEqual(Ms2.shape[1], Ns_all[1])

        # Most likely only one base station (the one with the worst
        # channel) will employ a precoder with total power of `Pu`,
        # while the other base stations will use less power.
        tol = 1e-10
        self.assertGreaterEqual(iPu + tol, np.linalg.norm(Ms1, 'fro')**2)
        # 1e-12 is included to avoid false test fails due to small
        # precision errors
        self.assertGreaterEqual(iPu + tol, np.linalg.norm(Ms2, 'fro')**2)

        # Test if the precoder block diagonalizes the channel
        self.assertNotAlmostEqual(np.linalg.norm(np.dot(H1, Ms1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, Ms2), 'fro'), 0)
        self.assertNotAlmostEqual(np.linalg.norm(np.dot(H2, Ms2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, Ms1), 'fro'), 0)

        # Equivalent sinrs (in linear scale)
        sinrs = np.empty(K, dtype=np.ndarray)
        sinrs[0] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H1, Ms1), Wk_all[0], noise_plus_int_cov_matrix[0])
        sinrs[1] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H2, Ms2), Wk_all[1], noise_plus_int_cov_matrix[1])

        # Spectral efficiency
        # noinspection PyPep8
        se = (np.sum(
            psk_obj.calcTheoreticalSpectralEfficiency(linear2dB(
                sinrs[0]), packet_length)) + np.sum(
                    psk_obj.calcTheoreticalSpectralEfficiency(
                        linear2dB(sinrs[1]), packet_length)))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Now with the Naive Stream Reduction xxxxxxxxxxxxxxxxxxxxxxx
        num_streams = 1
        enhancedBD_obj.set_ext_int_handling_metric(
            'naive', {'num_streams': num_streams})

        (MsPk_naive_all, Wk_naive_all, Ns_naive_all) \
            = enhancedBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        MsPk_naive_1 = MsPk_naive_all[0]
        MsPk_naive_2 = MsPk_naive_all[1]

        self.assertEqual(MsPk_naive_1.shape[1], Ns_naive_all[0])
        self.assertEqual(MsPk_naive_2.shape[1], Ns_naive_all[1])
        self.assertEqual(Ns_naive_all[0], num_streams)
        self.assertEqual(Ns_naive_all[1], num_streams)

        # Test if the square of the Frobenius norm of the precoder of each
        # user is equal to the power available to that user.
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_naive_1, 'fro')**2)
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_naive_2, 'fro')**2)

        # Test if MsPk really block diagonalizes the channel
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H1, MsPk_naive_1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, MsPk_naive_2), 'fro'),
                               0)
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H2, MsPk_naive_2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, MsPk_naive_1), 'fro'),
                               0)

        sinrs4 = np.empty(K, dtype=np.ndarray)
        sinrs4[0] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H1, MsPk_naive_1), Wk_naive_all[0],
            noise_plus_int_cov_matrix[0])
        sinrs4[1] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H2, MsPk_naive_2), Wk_naive_all[1],
            noise_plus_int_cov_matrix[1])

        # Spectral efficiency
        # se4 = (
        #     np.sum(psk_obj.calcTheoreticalSpectralEfficiency(
        #         linear2dB(sinrs4[0]),
        #         packet_length))
        #     +
        #     np.sum(psk_obj.calcTheoreticalSpectralEfficiency(
        #         linear2dB(sinrs4[1]),
        #         packet_length)))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Now with the Fixed Stream Reduction xxxxxxxxxxxxxxxxxxxxxxx
        # The 'fixed' metric requires that metric_func_extra_args_dict is
        # provided and has the 'num_streams' key. If this is not the case
        # an exception is raised
        with self.assertRaises(AttributeError):
            enhancedBD_obj.set_ext_int_handling_metric('fixed')

        # Now let's test the fixed metric
        num_streams = 1
        enhancedBD_obj.set_ext_int_handling_metric(
            'fixed', {'num_streams': num_streams})

        (MsPk_fixed_all, Wk_fixed_all, Ns_fixed_all) \
            = enhancedBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        MsPk_fixed_1 = MsPk_fixed_all[0]
        MsPk_fixed_2 = MsPk_fixed_all[1]

        self.assertEqual(MsPk_fixed_1.shape[1], Ns_fixed_all[0])
        self.assertEqual(MsPk_fixed_2.shape[1], Ns_fixed_all[1])
        self.assertEqual(Ns_fixed_all[0], num_streams)
        self.assertEqual(Ns_fixed_all[1], num_streams)

        # Test if the square of the Frobenius norm of the precoder of each
        # user is equal to the power available to that user.
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_fixed_1, 'fro')**2)
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_fixed_2, 'fro')**2)

        # Test if MsPk really block diagonalizes the channel
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H1, MsPk_fixed_1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, MsPk_fixed_2), 'fro'),
                               0)
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H2, MsPk_fixed_2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, MsPk_fixed_1), 'fro'),
                               0)

        sinrs5 = np.empty(K, dtype=np.ndarray)
        sinrs5[0] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H1, MsPk_fixed_1), Wk_fixed_all[0],
            noise_plus_int_cov_matrix[0])
        sinrs5[1] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H2, MsPk_fixed_2), Wk_fixed_all[1],
            noise_plus_int_cov_matrix[1])

        # Spectral efficiency
        # se5 = (
        #     np.sum(psk_obj.calcTheoreticalSpectralEfficiency(
        #         linear2dB(sinrs5[0]),
        #         packet_length))
        #     +
        #     np.sum(psk_obj.calcTheoreticalSpectralEfficiency(
        #         linear2dB(sinrs5[1]),
        #         packet_length)))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Handling external interference xxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # Handling external interference using the capacity metric
        enhancedBD_obj.set_ext_int_handling_metric('capacity')
        (MsPk_all, Wk_cap_all, Ns_cap_all) \
            = enhancedBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        MsPk_cap_1 = MsPk_all[0]
        MsPk_cap_2 = MsPk_all[1]

        self.assertEqual(MsPk_cap_1.shape[1], Ns_cap_all[0])
        self.assertEqual(MsPk_cap_2.shape[1], Ns_cap_all[1])

        # Test if the square of the Frobenius norm of the precoder of each
        # user is equal to the power available to that user.
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_cap_1, 'fro')**2)
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_cap_2, 'fro')**2)

        # Test if MsPk really block diagonalizes the channel
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H1, MsPk_cap_1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, MsPk_cap_2), 'fro'),
                               0)
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H2, MsPk_cap_2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, MsPk_cap_1), 'fro'),
                               0)

        sinrs2 = np.empty(K, dtype=np.ndarray)
        sinrs2[0] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H1, MsPk_cap_1), Wk_cap_all[0],
            noise_plus_int_cov_matrix[0])
        sinrs2[1] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H2, MsPk_cap_2), Wk_cap_all[1],
            noise_plus_int_cov_matrix[1])

        # Spectral efficiency
        # noinspection PyPep8
        se2 = (np.sum(
            psk_obj.calcTheoreticalSpectralEfficiency(linear2dB(
                sinrs2[0]), packet_length)) + np.sum(
                    psk_obj.calcTheoreticalSpectralEfficiency(
                        linear2dB(sinrs2[1]), packet_length)))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Handling external interference xxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # Handling external interference using the effective_throughput metric
        enhancedBD_obj.set_ext_int_handling_metric(
            'effective_throughput', {
                'modulator': psk_obj,
                'packet_length': packet_length
            })

        (MsPk_effec_all, Wk_effec_all, Ns_effec_all) \
            = enhancedBD_obj.block_diagonalize_no_waterfilling(
            multiUserChannel)
        MsPk_effec_1 = MsPk_effec_all[0]
        MsPk_effec_2 = MsPk_effec_all[1]

        self.assertEqual(MsPk_effec_1.shape[1], Ns_effec_all[0])
        self.assertEqual(MsPk_effec_2.shape[1], Ns_effec_all[1])

        # Test if the square of the Frobenius norm of the precoder of each
        # user is equal to the power available to that user.
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_effec_1, 'fro')**2)
        self.assertAlmostEqual(iPu, np.linalg.norm(MsPk_effec_2, 'fro')**2)

        # Test if MsPk really block diagonalizes the channel
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H1, MsPk_effec_1), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H1, MsPk_effec_2), 'fro'),
                               0)
        self.assertNotAlmostEqual(
            np.linalg.norm(np.dot(H2, MsPk_effec_2), 'fro'), 0)
        self.assertAlmostEqual(np.linalg.norm(np.dot(H2, MsPk_effec_1), 'fro'),
                               0)

        sinrs3 = np.empty(K, dtype=np.ndarray)
        sinrs3[0] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H1, MsPk_effec_1), Wk_effec_all[0],
            noise_plus_int_cov_matrix[0])
        sinrs3[1] = blockdiagonalization.EnhancedBD._calc_linear_SINRs(
            np.dot(H2, MsPk_effec_2), Wk_effec_all[1],
            noise_plus_int_cov_matrix[1])

        # Spectral efficiency
        # noinspection PyPep8
        se3 = (np.sum(
            psk_obj.calcTheoreticalSpectralEfficiency(linear2dB(
                sinrs3[0]), packet_length)) + np.sum(
                    psk_obj.calcTheoreticalSpectralEfficiency(
                        linear2dB(sinrs3[1]), packet_length)))
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # Test if the effective_throughput obtains a better spectral
        # efficiency then the capacity and not handling interference.
        self.assertGreater(se3 + tol, se2)
        self.assertGreater(se3 + tol, se)