Ejemplo n.º 1
0
    def calc_path_loss_dB(self, d, **kargs):
        """
        Calculates the Path Loss (in dB) for a given distance (in Km).

        Note that the returned value is positive, but should be understood
        as "a loss".

        Parameters
        ----------
        d : float or numpy array
            Distance (in Km)
        kargs : dict
            Optional parameters for use in subclasses if required.

        Other Parameters
        ----------------
        kwargs : dict
            Additional keywords that might be necessary in a subclass.

        Returns
        -------
        PL : float or numpy array
            Path loss (in dB) for the given distance(s).
        """
        PL = self._calc_deterministic_path_loss_dB(d, **kargs)
        if self.use_shadow_bool is True:  # pragma: no cover
            if isinstance(d, Iterable):
                # If 'd' is a numpy array (or something similar such as a
                # list), shadow must be a numpy array with the same shape
                shadow = conversion.dB2Linear(
                    np.random.standard_normal(np.size(d)) * self.sigma_shadow)
                shadow.shape = np.shape(d)
            else:
                # If 'd' is not an array but add a scalar shadowing
                shadow = conversion.dB2Linear(
                    np.random.standard_normal() * self.sigma_shadow)
            PL += shadow

        # The calculated path loss (in dB) must be positive. If it is not
        # positive that means that the distance 'd' is too small.
        if np.any(np.array(PL) < 0):
            if self.handle_small_distances_bool is True:
                if isinstance(PL, Iterable):
                    # If PL is the path loss for multiple distance values
                    # and one (or more) of the path loss values is (are)
                    # negative, set them to to zero (no path loss).
                    PL[PL < 0] = 0.0
                else:
                    # If PL is the path loss for a single distance value
                    # and it is negative (the distance is too small), let's
                    # assume the path loss is equal to 0dB
                    PL = 0.0
            else:
                msg = ("The distance is too small to calculate a valid"
                       " path loss.")
                raise RuntimeError(msg.format(d))
        return PL
Ejemplo n.º 2
0
    def _calcTheoreticalSingleCarrierErrorRate(self, SNR):
        """
        Calculates the theoretical (approximation) error rate of a single
        carrier in the QAM system (QAM has two carriers).

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        Psc : float | np.ndarray
            The theoretical single carrier error rate.

        Notes
        -----
        This method is used in the :meth:`calcTheoreticalSER`
        implementation.

        See also
        --------
        calcTheoreticalSER

        """
        snr = dB2Linear(SNR)
        # Probability of error of each carrier in a square QAM
        # $P_{sc} = 2\left(1 - \frac{1}{\sqrt M}\right)Q\left(\sqrt{\frac{3}{M-1}\frac{E_s}{N_0}}\right)$
        sqrtM = np.sqrt(self._M)
        Psc = (2. * (1. - (1. / sqrtM)) *
               qfunc(np.sqrt(snr * 3. / (self._M - 1.))))
        return Psc
Ejemplo n.º 3
0
    def _calc_transmit_power(SNR_dB, noise_var, path_loss=1.0):
        """
        Calculates the required transmit power (in linear scale) to
        achieve the desired mean SNR value at the cell border.

        This method calculates the path loss at the cell border and
        then finds the transmit power that gives the desired mean SNR
        at the cell border.

        Parameters
        ----------
        SNR_dB : float
            SNR value (in dB)
        noise_var : float
            Noise variance
        path_loss : float
            Path loss (in linear scale) to consider in the transmit power
            calculation. The case without considering path loss corresponds
            to path_loss=1.

        Returns
        -------
        transmit_power : float
            Desired transmit power (in linear scale).
        """
        snr = dB2Linear(SNR_dB)
        pt = snr * noise_var / path_loss
        return pt
Ejemplo n.º 4
0
    def _calc_transmit_power(SNR_dB, N0_dBm, cell_radius, path_loss_obj):
        """
        Calculates the required transmit power (in linear scale) to
        achieve the desired mean SNR value at the cell border.

        This method calculates the path loss at the cell border and
        then finds the transmit power that gives the desired mean SNR
        at the cell border.

        Parameters
        ----------
        SNR_dB : float
            SNR value (in dB)
        N0_dBm : float
            Noise power (in dBm)
        cell_radius : float
            Cell radius (in Km)
        path_loss_obj : Path Loss object
            Object of a pathloss class used to calculate the path loss (see
            `comm.pathloss`.

        Returns
        -------
        transmit_power : float
            Desired transmit power (in linear scale).
        """
        # Path loss (in linear scale) from the cell center to
        path_loss_border = path_loss_obj.calc_path_loss(cell_radius)
        snr = dB2Linear(SNR_dB)
        pt = snr * dBm2Linear(N0_dBm) / path_loss_border
        return pt
Ejemplo n.º 5
0
    def _calc_transmit_power(SNR_dB, N0_dBm, cell_radius, path_loss_obj):
        """
        Calculates the required transmit power (in linear scale) to
        achieve the desired mean SNR value at the cell border.

        This method calculates the path loss at the cell border and
        then finds the transmit power that gives the desired mean SNR
        at the cell border.

        Parameters
        ----------
        SNR_dB : float
            SNR value (in dB)
        N0_dBm : float
            Noise power (in dBm)
        cell_radius : float
            Cell radius (in Km)
        path_loss_obj : Path Loss object
            Object of a pathloss class used to calculate the path loss (see
            `comm.pathloss`.

        Returns
        -------
        transmit_power : float
            Desired transmit power (in linear scale).
        """
        # Path loss (in linear scale) from the cell center to
        path_loss_border = path_loss_obj.calc_path_loss(cell_radius)
        snr = dB2Linear(SNR_dB)
        pt = snr * dBm2Linear(N0_dBm) / path_loss_border
        return pt
Ejemplo n.º 6
0
    def _calc_transmit_power(SNR_dB, noise_var, path_loss=1.0):
        """
        Calculates the required transmit power (in linear scale) to
        achieve the desired mean SNR value at the cell border.

        This method calculates the path loss at the cell border and
        then finds the transmit power that gives the desired mean SNR
        at the cell border.

        Parameters
        ----------
        SNR_dB : float
            SNR value (in dB)
        noise_var : float
            Noise variance
        path_loss : float
            Path loss (in linear scale) to consider in the transmit power
            calculation. The case without considering path loss corresponds
            to path_loss=1.

        Returns
        -------
        transmit_power : float
            Desired transmit power (in linear scale).
        """
        snr = dB2Linear(SNR_dB)
        pt = snr * noise_var / path_loss
        return pt
Ejemplo n.º 7
0
def simulate_for_a_given_ap_assoc(pl, ap_assoc, wall_losses_dB, Pt, noise_var):
    """
    Simulate and return the SINR for a given path loss and AP associations.

    This is an internal function called inside
    `perform_simulation_SINR_heatmap`

    Parameters
    ----------
    pl : 5D numpy float array
        The path loss (in LINEAR SCALE) from each discrete position in each
        room to each access point. Dimension: (n, n, d, d, a) where 'n' is
        the number of rooms per dimension, 'd' is the number of discrete
        positions in one room (per dimension) and 'a' is the number of
        access points.
    ap_assoc : 4D numpy int array
        The index of the access point that each discrete point in each room
        is associated with. Dimension: (n, n, d, d)
    wall_losses_dB : 5D numpy int array
        The wall losses (in dB) from each discrete user in each room to
        each access point. Dimension: (n, n, d, d, a)
    Pt : float
        Transmit power.
    noise_var : float
        Noise variance (power)

    Returns
    -------
    sinr_array_dB : 4D numpy array
        The SINR (in dB) of each discrete point of each room.
    """
    wall_losses = dB2Linear(-wall_losses_dB)

    # Number of APs is the last dimension in the path loss array
    num_aps = pl.shape[-1]

    # Output variable
    sinr_array = np.empty(ap_assoc.shape, dtype=float)

    for ap_idx in range(num_aps):
        # Mask of the users associated with the current access point
        mask = (ap_assoc == ap_idx)

        # # Mask of the users NOT associated with the current access point
        # mask_n = np.logical_not(mask)

        # Mask with all APs except the current one (that is, the
        # interfering APs)
        mask_i_aps = np.arange(num_aps) != ap_idx

        # Each element in desired_power is the desired power of one user
        # associated with the current access point
        desired_power = Pt * wall_losses[mask, ap_idx] * pl[mask, ap_idx]
        undesired_power = np.sum(Pt * wall_losses[mask][:, mask_i_aps] *
                                 pl[mask][:, mask_i_aps],
                                 axis=-1)

        sinr_array[mask] = (desired_power / (undesired_power + noise_var))

    return linear2dB(sinr_array)
Ejemplo n.º 8
0
def simulate_and_compute_Rxx_U0(M, N, SNR, beam_sep):
    """
    Simulate and generate Rxx and U0 considering that three wavefronts were
    sent.

    M : int
    N : int
    SNR : float
    beam_sep : float
        Normalized beamwidth separation between the wavefronts. This separation
        is normalized by the beamwidth.
    """
    qpsk = modulators.QPSK()

    d = 3  # Number of inpinging waves
    mu_b = 2 * np.pi / M
    mu = np.array([-beam_sep * mu_b, 0, beam_sep * mu_b])  # Standard beamwidth

    data = np.random.randint(4, size=(d, N))
    modulated_data = qpsk.modulate(data) / sqrt(d)
    noise_power = 1. / dB2Linear(SNR)
    noise = sqrt(noise_power) * randn_c(M, N)
    steering_vec = calc_a_phi_vect(M, mu)
    received_data = steering_vec @ modulated_data + noise

    # Covariance matrix of the received Data
    Rxx = received_data @ received_data.T.conj()
    U, S, V_H = np.linalg.svd(Rxx)
    U0 = U[:, d:]

    return Rxx, U0
Ejemplo n.º 9
0
    def _calcTheoreticalSingleCarrierErrorRate(self, SNR):
        """
        Calculates the theoretical (approximation) error rate of a single
        carrier in the QAM system (QAM has two carriers).

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        Psc : float | np.ndarray
            The theoretical single carrier error rate.

        Notes
        -----
        This method is used in the :meth:`calcTheoreticalSER`
        implementation.

        See also
        --------
        calcTheoreticalSER

        """
        snr = dB2Linear(SNR)
        # Probability of error of each carrier in a square QAM
        # $P_{sc} = 2\left(1 - \frac{1}{\sqrt M}\right)Q\left(\sqrt{\frac{3}{M-1}\frac{E_s}{N_0}}\right)$
        sqrtM = np.sqrt(self._M)
        Psc = (2. * (1. - (1. / sqrtM)) *
               qfunc(np.sqrt(snr * 3. / (self._M - 1.))))
        return Psc
Ejemplo n.º 10
0
def simulate_for_a_given_ap_assoc(pl, ap_assoc, wall_losses_dB, Pt, noise_var):
    """
    Simulate and return the SINR for a given path loss and AP associations.

    This is an internal function called inside
    `perform_simulation_SINR_heatmap`

    Parameters
    ----------
    pl : 5D numpy float array
        The path loss (in LINEAR SCALE) from each discrete position in each
        room to each access point. Dimension: (n, n, d, d, a) where 'n' is
        the number of rooms per dimension, 'd' is the number of discrete
        positions in one room (per dimension) and 'a' is the number of
        access points.
    ap_assoc : 4D numpy int array
        The index of the access point that each discrete point in each room
        is associated with. Dimension: (n, n, d, d)
    wall_losses_dB : 5D numpy int array
        The wall losses (in dB) from each discrete user in each room to
        each access point. Dimension: (n, n, d, d, a)
    Pt : float
        Transmit power.
    noise_var : float
        Noise variance (power)

    Returns
    -------
    sinr_array_dB : 4D numpy array
        The SINR (in dB) of each discrete point of each room.
    """
    wall_losses = dB2Linear(-wall_losses_dB)

    # Number of APs is the last dimension in the path loss array
    num_aps = pl.shape[-1]

    # Output variable
    sinr_array = np.empty(ap_assoc.shape, dtype=float)

    for ap_idx in range(num_aps):
        # Mask of the users associated with the current access point
        mask = ap_assoc == ap_idx

        # # Mask of the users NOT associated with the current access point
        # mask_n = np.logical_not(mask)

        # Mask with all APs except the current one (that is, the
        # interfering APs)
        mask_i_aps = np.arange(num_aps) != ap_idx

        # Each element in desired_power is the desired power of one user
        # associated with the current access point
        desired_power = Pt * wall_losses[mask, ap_idx] * pl[mask, ap_idx]
        undesired_power = np.sum(Pt * wall_losses[mask][:, mask_i_aps] * pl[mask][:, mask_i_aps], axis=-1)

        sinr_array[mask] = desired_power / (undesired_power + noise_var)

    return linear2dB(sinr_array)
Ejemplo n.º 11
0
    def test_calc_effective_throughput(self):
        psk_obj = fundamental.PSK(8)
        packet_length = 60

        SINRs_dB = np.array([11.4, 20.3])
        sinrs_linear = dB2Linear(SINRs_dB)

        expected_spectral_efficiency = np.sum(
            psk_obj.calcTheoreticalSpectralEfficiency(SINRs_dB, packet_length))

        spectral_efficiency = blockdiagonalization._calc_effective_throughput(
            sinrs_linear, psk_obj, packet_length)

        np.testing.assert_array_almost_equal(spectral_efficiency,
                                             expected_spectral_efficiency)
Ejemplo n.º 12
0
    def test_calc_effective_throughput(self):
        psk_obj = fundamental.PSK(8)
        packet_length = 60

        SINRs_dB = np.array([11.4, 20.3])
        sinrs_linear = dB2Linear(SINRs_dB)

        expected_spectral_efficiency = np.sum(
            psk_obj.calcTheoreticalSpectralEfficiency(SINRs_dB, packet_length))

        spectral_efficiency = blockdiagonalization._calc_effective_throughput(
            sinrs_linear, psk_obj, packet_length)

        np.testing.assert_array_almost_equal(spectral_efficiency,
                                             expected_spectral_efficiency)
Ejemplo n.º 13
0
    def calc_path_loss(self, d, **kargs):
        """
        Calculates the path loss (linear scale) for a given distance (in Km).

        Parameters
        ----------
        d : float or numpy array
            Distance (in Km)
        kargs : dict
            Additional keywords that might be necessary in a subclass.

        Returns
        -------
        pl : float or numpy array
            Path loss (in linear scale) for the given distance(s).
        """
        pl = conversion.dB2Linear(-self.calc_path_loss_dB(d))
        return pl
Ejemplo n.º 14
0
    def calcTheoreticalSER(self, SNR):
        """Calculates the theoretical (approximation) symbol error rate for
        the BPSK scheme.

        Parameters
        ----------
        SNR : float or array like
            Signal-to-noise-value (in dB).

        Returns
        -------
        SER : float or array like
            The theoretical symbol error rate.
        """
        snr = dB2Linear(SNR)
        # $P_b = Q\left(\sqrt{\frac{2E_b}{N_0}}\right)$
        # Alternative formula (same result)
        # $P_b = \frac{1}{2}erfc \left ( \sqrt{\frac{E_b}{N_0}} \right )$
        ser = qfunc(np.sqrt(2 * snr))
        return ser
Ejemplo n.º 15
0
    def calcTheoreticalSER(self, SNR):
        """
        Calculates the theoretical (approximation) symbol error rate for
        the BPSK scheme.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        SER : float | np.ndarray
            The theoretical symbol error rate.
        """
        snr = dB2Linear(SNR)
        # $P_b = Q\left(\sqrt{\frac{2E_b}{N_0}}\right)$
        # Alternative formula (same result)
        # $P_b = \frac{1}{2}erfc \left ( \sqrt{\frac{E_b}{N_0}} \right )$
        ser = qfunc(np.sqrt(2 * snr))
        return ser
Ejemplo n.º 16
0
    def calcTheoreticalSER(self, SNR):
        """Calculates the theoretical (approximation for high M and high
        SNR) symbol error rate for the M-PSK scheme.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        SER : float | np.ndarray
            The theoretical symbol error rate.
        """
        snr = dB2Linear(SNR)

        # $P_s \approx 2Q\left(\sqrt{2\gamma_s}\sin\frac{\pi}{M}\right)$
        # Alternative formula (same result)
        # $P_s = erfc \left ( \sqrt{\gamma_s} \sin(\frac{\pi}{M})  \right )$
        ser = 2. * qfunc(np.sqrt(2. * snr) * math.sin(PI / self._M))
        return ser
Ejemplo n.º 17
0
    def calcTheoreticalSER(self, SNR):
        """Calculates the theoretical (approximation for high M and high
        SNR) symbol error rate for the M-PSK scheme.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        SER : float | np.ndarray
            The theoretical symbol error rate.
        """
        snr = dB2Linear(SNR)

        # $P_s \approx 2Q\left(\sqrt{2\gamma_s}\sin\frac{\pi}{M}\right)$
        # Alternative formula (same result)
        # $P_s = erfc \left ( \sqrt{\gamma_s} \sin(\frac{\pi}{M})  \right )$
        ser = 2. * qfunc(np.sqrt(2. * snr) * math.sin(PI / self._M))
        return ser
Ejemplo n.º 18
0
    def calc_path_loss(self, d, **kargs):  # pragma: no cover
        """
        Calculates the path loss (linear scale) for a given distance (in Km).

        Parameters
        ----------
        d : float or numpy array
            Distance (in Km)
        kargs : dict
            Extra named parameters. This is used in subclasses for extra
            parameters for the path loss calculation.

        Other Parameters
        ----------------
        kwargs : dict
            Additional keywords that might be necessary in a subclass.

        Returns
        -------
        pl : float or numpy array
            Path loss (in linear scale) for the given distance(s).
        """
        pl = conversion.dB2Linear(-self.calc_path_loss_dB(d, **kargs))
        return pl
Ejemplo n.º 19
0
    def _run_simulation(self, current_parameters):
        # To make sure that this function does not modify the object state,
        # we sobrescibe self to None.
        #self = None

        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        NSymbs = current_parameters["NSymbs"]
        M = current_parameters["M"]
        SNR = current_parameters["SNR"]
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        inputData = np.random.randint(0, M, NSymbs)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        modulatedData = self.modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        noiseVar = 1 / dB2Linear(SNR)
        noise = ((np.random.standard_normal(NSymbs) +
                  1j * np.random.standard_normal(NSymbs)) *
                 np.sqrt(noiseVar / 2))
        receivedData = modulatedData + noise
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate received data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        demodulatedData = self.modulator.demodulate(receivedData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = sum(inputData != demodulatedData)
        bitErrors = misc.count_bit_errors(inputData, demodulatedData)
        numSymbols = inputData.size
        numBits = inputData.size * mod.level2bits(M)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create(
            "symbol_errors", Result.SUMTYPE, symbolErrors)

        numSymbolsResult = Result.create(
            "num_symbols", Result.SUMTYPE, numSymbols)

        bitErrorsResult = Result.create("bit_errors", Result.SUMTYPE, bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits)

        serResult = Result.create(
            "ser", Result.RATIOTYPE, symbolErrors, numSymbols)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)

        return simResults
Ejemplo n.º 20
0
# External Interference Parameters
Pe_dBm = -10000  # transmit power (in dBm) of the ext. interference
ext_int_rank = 1  # Rank of the external interference

# xxxxxxxxxx General Parameters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
rep_max = 20000  # Maximum number of repetitions for each

pbar = progressbar.ProgressbarText(rep_max, message="Simulating for SNR: {0}".format(SNR_dB))

# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxx Dependent parameters (don't change these) xxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Path loss (in linear scale) from the cell center to
path_loss_border = path_loss_obj.calc_path_loss(cell_radius)
noise_var = conversion.dBm2Linear(N0_dBm)
snr = conversion.dB2Linear(SNR_dB)
transmit_power = snr * noise_var / path_loss_border
# External interference power
pe = conversion.dBm2Linear(Pe_dBm)

# Cell Grid
cell_grid = cell.Grid()
cell_grid.create_clusters(num_clusters, num_cells, cell_radius)
# noinspection PyProtectedMember
cluster0 = cell_grid._clusters[0]
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# xxxxxxxxxx Create the scenario xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cell_ids = np.arange(1, num_cells + 1)
Ejemplo n.º 21
0
    codebook_size = 5
    dimension = 4
    C = gen_codebook(codebook_size, dimension)

    Nt = 2
    Nr = 2
    K = 3

    H = misc.randn_c(Nr * K, Nt * K)

    Hquant = my_quant_func(H, Nr, Nt, K, C)


if __name__ == '__main__':
    SNR = 15.0
    noise_var = 1 / dB2Linear(SNR)
    M = 2
    NSymbs = 50
    rep_max = 300
    modulator = fundamental.BPSK()
    K = 3
    Nr = np.ones(K, dtype=int) * 2
    Nt = np.ones(K, dtype=int) * 2
    Ns = np.ones(K, dtype=int) * 1
    multi_user_channel = pyphysim.channels.multiuser.MultiUserChannelMatrix()
    multi_user_channel_quant = pyphysim.channels.multiuser.MultiUserChannelMatrix()
    multi_user_channel.noise_var = noise_var
    multi_user_channel_quant.noise_var = noise_var

    ia_solver = algorithms.MaxSinrIASolver(multi_user_channel_quant)
    ia_solver.max_iterations = 120
Ejemplo n.º 22
0
 def test_dB2Linear(self):
     self.assertAlmostEqual(conversion.dB2Linear(30),
                            1000.0)
Ejemplo n.º 23
0
def perform_simulation(
        scenario_params,  # pylint: disable=R0914
        power_params,
        plot_results_bool=True):
    """
    Run the simulation.
    """
    # xxxxxxxxxx Simulation Scenario Configuration xxxxxxxxxxxxxxxxxxxxxxxx
    # The size of the side of each square room
    side_length = scenario_params['side_length']
    # How much (in dB) is lost for each wall teh signal has to pass
    single_wall_loss_dB = scenario_params['single_wall_loss_dB']

    # Square of 12 x 12 square rooms
    num_rooms_per_side = scenario_params['num_rooms_per_side']
    # Total number of rooms in the grid
    num_rooms = num_rooms_per_side**2

    # 1 means 1 ap every room. 2 means 1 ap every 2 rooms and so on. Valid
    # values are: 1, 2, 4 and 9.
    ap_decimation = scenario_params['ap_decimation']
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Simulation Power Configuration xxxxxxxxxxxxxxxxxxxxxxxxxxx
    # Transmit power of each access point
    Pt_dBm = power_params['Pt_dBm']
    noise_power_dBm = power_params['noise_power_dBm']

    Pt = dBm2Linear(Pt_dBm)  # 20 dBm transmit power
    noise_var = dBm2Linear(noise_power_dBm)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the positions of all rooms xxxxxxxxxxxxxxxxxxxxx
    room_positions = calc_room_positions_square(side_length, num_rooms)
    room_positions.shape = (num_rooms_per_side, num_rooms_per_side)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Create the path loss object xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    pl_metis_ps7_obj = pathloss.PathLossMetisPS7()
    pl_metis_ps7_obj.handle_small_distances_bool = True
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Add users in random positions in the 2D grid xxxxxxxxxxxxx
    num_users = 100  # We will create this many users in the 2D grid
    users_positions = (num_rooms_per_side * side_length *
                       (np.random.random_sample(num_users) +
                        1j * np.random.random_sample(num_users) - 0.5 - 0.5j))
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx AP Allocation xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # 1 AP in each room
    ap_positions = get_ap_positions(room_positions, ap_decimation)
    num_aps = ap_positions.size
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate distances: each user to each AP xxxxxxxxxxxxxxxx
    # Dimension: (num_users, num_APs)
    dists_m = np.abs(users_positions[:, np.newaxis] -
                     ap_positions[np.newaxis, :])
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Calculate AP association xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # INPUTS
    # Find in which room each user is
    users_rooms = np.argmin(np.abs(
        room_positions.reshape([-1, 1]) - users_positions[np.newaxis, :]),
                            axis=0)

    # Number of walls from each room to each other room
    num_walls_all_rooms = calc_num_walls(side_length, room_positions,
                                         ap_positions)
    # Number of walls from each room that has at least one user to each
    # room with an AP
    num_walls_rooms_with_users = num_walls_all_rooms[users_rooms]

    # Path loss from each user to each AP (no matter if it will be a
    # transmitting AP or not, since we still have to perform the AP
    # association)
    pl_all = pl_metis_ps7_obj.calc_path_loss(
        dists_m, num_walls=num_walls_rooms_with_users)

    # Calculate wall losses from each user to each AP (no matter if it will
    # be a transmitting AP or not, since we still have to perform the AP
    # association)
    wall_losses_dB_all = num_walls_rooms_with_users * single_wall_loss_dB

    # Calculate path loss plus wall losses (we multiply the linear values)
    # from each user to each AP (no matter if it will be a transmitting AP
    # or not, since we still have to perform the AP association)
    pl_all_plus_wl = pl_all * dB2Linear(-wall_losses_dB_all)

    # OUTPUTS
    # Determine with which AP each user is associated with.
    # Each user will associate with the CLOSEST access point.
    ap_assoc = find_ap_assoc_best_channel(pl_all_plus_wl)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Find which Access Points should stay on xxxxxxxxxxxxxxxxxx
    # Indexes of the active APs
    transmitting_aps, users_count = np.unique(ap_assoc, return_counts=True)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the SINRs for each path loss model xxxxxxxxxxxxx
    # Take the path loss plus wall losses only for the transmitting aps
    pl_all_plus_wall_losses_tx_aps = pl_all_plus_wl.take(transmitting_aps,
                                                         axis=1)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the SINRs and capacity xxxxxxxxxxxxxxxxxxxxxxxxx
    sinr_array_pl_metis_ps7_dB, capacity_metis_ps7 \
        = simulate_for_a_given_ap_assoc(
            pl_all_plus_wall_losses_tx_aps, ap_assoc,
            transmitting_aps, Pt, noise_var)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Plot the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    if plot_results_bool is True:
        print(("\nMin/Mean/Max SINR value (METIS PS7):"
               "\n    {0}\n    {1}\n    {2}").format(
                   sinr_array_pl_metis_ps7_dB.min(),
                   sinr_array_pl_metis_ps7_dB.mean(),
                   sinr_array_pl_metis_ps7_dB.max()))

        print(("\nMin/Mean/Max Capacity value (METIS PS7):"
               "\n    {0}\n    {1}\n    {2}").format(capacity_metis_ps7.min(),
                                                     capacity_metis_ps7.mean(),
                                                     capacity_metis_ps7.max()))

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # xxxxxxxxxxxxxxx Plot the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # Create a mask for the active APs
        transmitting_aps_mask = np.zeros(num_aps, dtype=bool)
        transmitting_aps_mask[transmitting_aps] = True

        # Save how many users are associated with each AP
        users_per_ap = np.zeros(num_aps, dtype=int)
        users_per_ap[transmitting_aps_mask] = users_count

        # xxxxxxxxxx Plot all rooms and users xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        all_rooms = [
            shapes.Rectangle(pos - side_length / 2. - side_length * 1j / 2.,
                             pos + side_length / 2. + side_length * 1j / 2.)
            for pos in room_positions.flatten()
        ]

        # Plot all Rooms and save the axis where they were plotted
        plt.figure(figsize=(10, 10))
        gs = gridspec.GridSpec(2, 1, height_ratios=[4, 1])
        # ax1 is where we will plot everything
        ax1 = plt.subplot(gs[0])
        ax1.set_xlabel("Position X coordinate")
        ax1.set_ylabel("Position Y coordinate")
        ax1.set_title("Plot of all Rooms")
        ax1.set_ylim([-60, 60])
        ax1.set_xlim([-60, 60])
        ax1 = plot_all_rooms(all_rooms, ax1)
        ax1.hold(True)

        # ax2 will be used for annotations
        ax2 = plt.subplot(gs[1])
        plt.setp(ax2.get_xticklabels(), visible=False)
        plt.setp(ax2.get_yticklabels(), visible=False)
        ax2.set_ylim([0, 10])
        ax2.set_xlim([0, 10])
        details = ax2.text(5,
                           5,
                           'Details',
                           verticalalignment='center',
                           horizontalalignment='center',
                           family='monospace')

        # Set the an array with colors for the access points. Transmitting APs
        # will be blue, while inactive APs will be gray
        ap_colors = np.empty(ap_positions.shape, dtype='U4')
        ap_colors[transmitting_aps_mask] = 'b'
        ap_colors[np.logical_not(transmitting_aps_mask)] = 'gray'

        # Plot the access points. We set linewidth to 0.0 so that there is no
        # border. We set the size ('s' keyword) to 50 to make it larger. The
        # colors are set according to the ap_colors array.
        # Note that we set a 5 points tolerance for the pick event.
        aps_plt = ax1.scatter(ap_positions.real,
                              ap_positions.imag,
                              marker='^',
                              c=ap_colors,
                              linewidths=0.1,
                              s=50,
                              picker=3)

        # Plot the users
        # Note that we set a 5 points tolerance for the pick event.
        users_plt = ax1.scatter(users_positions.real,
                                users_positions.imag,
                                marker='*',
                                c='r',
                                linewidth=0.1,
                                s=50,
                                picker=3)

        # xxxxxxxxxx Define a function to call for the pick_event Circle used
        # to select an AP. We will set its visibility to False here. When an AP
        # is selected, we move this circle to its position and set its
        # visibility to True.
        selected_ap_circle = ax1.plot([0], [0],
                                      'o',
                                      ms=12,
                                      alpha=0.4,
                                      color='yellow',
                                      visible=False)[0]

        # Define the callback function for the pick event
        def on_pick(event):
            """Callback for the pick event in the matplotlib plot."""
            # We will reset users colors on each pick
            users_colors = np.empty(ap_assoc.size, dtype='U1')
            users_colors[:] = 'r'

            # Index of the point clicked
            ind = event.ind[0]

            if event.artist == aps_plt:
                # Disable the circle in the AP
                selected_ap_circle.set_visible(False)

                if ind not in ap_assoc:
                    # Text information for the disabled AP
                    text = "AP {0} (Disabled)".format(ind)
                else:
                    # Text information for the selected AP
                    text = "AP {0} with {1} user(s)\nTotal throughput: {2:7.4f}"
                    text = text.format(
                        ind, users_per_ap[ind],
                        np.sum(capacity_metis_ps7[ap_assoc == ind]))

                    # Change the colors of the users associated with the
                    # current AP to green
                    users_colors[ap_assoc == ind] = 'g'

            elif event.artist == users_plt:
                # Text information for the selected user
                text = "User {0}\n    SINR: {1:7.4f}\nCapacity: {2:7.4f}".format(
                    ind, sinr_array_pl_metis_ps7_dB[ind],
                    capacity_metis_ps7[ind])

                # If there other users are associated with the same AP of the
                # current user
                if users_per_ap[ap_assoc[ind]] > 1:
                    text = "{0}\nShares AP with {1} other user(s)".format(
                        text, users_per_ap[ap_assoc[ind]] - 1)

                users_AP = ap_assoc[ind]
                # Plot a yellow circle in the user's AP
                ap_pos = ap_positions[users_AP]
                # CHange the collor of other users in the same AP to green and
                # the current user to cyan
                users_colors[ap_assoc == users_AP] = 'g'
                users_colors[ind] = 'c'

                selected_ap_circle.set_visible(True)
                selected_ap_circle.set_data([ap_pos.real], [ap_pos.imag])

            # Set users colors
            users_plt.set_color(users_colors)

            # Set the details text
            details.set_text(text)
            ax1.figure.canvas.draw()

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # Connect the on_pick function with the pick event
        ax1.figure.canvas.mpl_connect('pick_event', on_pick)

        plt.show()
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Return the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    return sinr_array_pl_metis_ps7_dB, capacity_metis_ps7
Ejemplo n.º 24
0
from pyphysim.channels.multiuser import MultiUserChannelMatrix
from pyphysim.ia import algorithms
from pyphysim.modulators.fundamental import PSK
from pyphysim.util.conversion import dB2Linear

if __name__ == '__main__':
    K = 3
    Nr = np.ones(K) * 4
    Nt = np.ones(K) * 4
    Ns = np.array([2, 2, 2])  # np.ones(K) * 2

    multiuserchannel = MultiUserChannelMatrix()
    modulator = PSK(4)

    SNR = 40
    noise_var = 1 / dB2Linear(SNR)
    print("SNR: {0}".format(SNR))
    print("noise_var: {0}".format(noise_var))

    multiuserchannel.randomize(Nr, Nt, K)
    multiuserchannel.noise_var = noise_var

    ia_solver = algorithms.AlternatingMinIASolver(multiuserchannel)
    ia_solver2 = algorithms.MMSEIASolver(multiuserchannel)
    ia_solver3 = algorithms.MaxSinrIASolver(multiuserchannel)

    ia_solver4 = algorithms.AlternatingMinIASolver(multiuserchannel)

    # ia_solver.initialize_with_closed_form = True
    # ia_solver2.initialize_with_closed_form = True
    # ia_solver3.initialize_with_closed_form = True
Ejemplo n.º 25
0
def main():
    """Main function.
    """
    K = 3
    Nr = 4
    Nt = 4
    Ns = 2
    SNR = 30.0
    P = 1.0

    # Dependent parameters
    noise_var = 1 / dB2Linear(SNR)

    RepMax = 1
    mmse_sinrs = np.empty([RepMax, K, Ns], dtype=float)
    max_sinr_sinrs = np.empty([RepMax, K, Ns], dtype=float)
    mmse_capacity = np.empty(RepMax, dtype=float)
    max_sinr_capacity = np.empty(RepMax, dtype=float)

    pbar = ProgressbarText(RepMax, message="Simulating for SNR: {0}".format(SNR))

    for rep in range(RepMax):
        # Creat the channel
        multiUserChannel = pyphysim.channels.multiuser.MultiUserChannelMatrix()
        multiUserChannel.randomize(Nr, Nt, K)
        multiUserChannel.noise_var = noise_var

        # Creat the IA solver object
        mmse_ia_solver = algorithms.MMSEIASolver(multiUserChannel)
        max_sinr_ia_solver = algorithms.MaxSinrIASolver(multiUserChannel)

        mmse_ia_solver.randomizeF(Ns, P)

        mmse_ia_solver.initialize_with = "fix"
        max_sinr_ia_solver.initialize_with = "fix"
        # noinspection PyProtectedMember
        max_sinr_ia_solver._F = mmse_ia_solver._F

        # mmse_ia_solver.initialize_with = 'fix'

        # We wouldn't need to explicitly set ia_solver.noise_var
        # variable if the multiUserChannel object had the correct value at
        # this point.
        # mmse_ia_solver.noise_var = noise_var
        mmse_ia_solver.max_iterations = 200
        mmse_ia_solver.solve(Ns)

        # max_sinr_ia_solver.noise_var = noise_var
        max_sinr_ia_solver.max_iterations = 200

        max_sinr_ia_solver.solve(Ns)

        mmse_sinrs[rep] = list(map(linear2dB, mmse_ia_solver.calc_SINR()))
        max_sinr_sinrs[rep] = list(map(linear2dB, max_sinr_ia_solver.calc_SINR()))

        mmse_capacity[rep] = np.sum(calc_capacity(mmse_ia_solver.calc_SINR()))
        max_sinr_capacity[rep] = np.sum(calc_capacity(max_sinr_ia_solver.calc_SINR()))

        # print "MMSE Alt. SINRs:\n{0}".format(np.vstack(mmse_sinrs[rep]))
        # print "Max SINR Alg. SINRs:\n{0}".format(np.vstack(max_sinr_sinrs[rep]))

        # print "MMSE Alt. Capacity: {0}".format(np.sum(calc_capacity(mmse_sinrs[rep])))
        # print "Max SINR Alg. Capacity: {0}".format(np.sum(calc_capacity(max_sinr_sinrs[rep])))
        # print

        pbar.progress(rep)

    print("MMSE Average SINRs:\n{0}".format(mmse_sinrs.mean(0)))
    print("Max SINR Average SINRs:\n{0}".format(max_sinr_sinrs.mean(0)))
    print("MMSE Average Capacity: {0}".format(mmse_capacity.mean()))
    print("Max SINR Average Capacity: {0}".format(max_sinr_capacity.mean()))

    print("\nEnd!")
Ejemplo n.º 26
0
    def _run_simulation(self, current_parameters):
        """The _run_simulation method is where the actual code to simulate
        the system is.

        The implementation of this method is required by every subclass of
        SimulationRunner.
        """
        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        NSymbs = current_parameters['NSymbs']
        modulator = current_parameters['modulator']
        M = modulator.M
        SNR = current_parameters["SNR"]
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        inputData = np.random.randint(0, M, NSymbs)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        modulatedData = modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        noiseVar = 1. / dB2Linear(SNR)
        noise = misc.randn_c(NSymbs) * np.sqrt(noiseVar)
        receivedData = modulatedData + noise
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate received data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        demodulatedData = modulator.demodulate(receivedData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = sum(inputData != demodulatedData)
        bitErrors = misc.count_bit_errors(inputData, demodulatedData)
        numSymbols = inputData.size
        numBits = inputData.size * fundamental.level2bits(M)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create(
            "symbol_errors", Result.SUMTYPE, symbolErrors)

        numSymbolsResult = Result.create(
            "num_symbols", Result.SUMTYPE, numSymbols)

        bitErrorsResult = Result.create(
            "bit_errors", Result.SUMTYPE, bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits)

        serResult = Result.create(
            "ser", Result.RATIOTYPE, symbolErrors, numSymbols)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        return simResults
Ejemplo n.º 27
0
    def _run_simulation(self, current_parameters):
        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        NSymbs = current_parameters["NSymbs"]
        M = self.modulator.M
        Nr = current_parameters["Nr"]
        Nt = current_parameters["Nt"]
        SNR = current_parameters["SNR"]
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Create the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        channel = misc.randn_c(Nr, Nt)
        self.mimo_object.set_channel_matrix(channel)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        num_layers = self.mimo_object.getNumberOfLayers()
        inputData = np.random.randint(0, M, NSymbs * num_layers)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        modulatedData = self.modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Encode with the MIMO scheme xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        transmit_signal = self.mimo_object.encode(modulatedData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        noiseVar = 1 / dB2Linear(SNR)
        awgn_noise = (misc.randn_c(Nr, NSymbs) * np.sqrt(noiseVar))
        received_signal = np.dot(channel, transmit_signal) + awgn_noise
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Decode with the MIMO Scheme xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        mimo_decoded_data = self.mimo_object.decode(received_signal)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate received data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        demodulatedData = self.modulator.demodulate(mimo_decoded_data)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = sum(inputData != demodulatedData)
        bitErrors = misc.count_bit_errors(inputData, demodulatedData)
        numSymbols = inputData.size
        numBits = inputData.size * fundamental.level2bits(M)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create(
            "symbol_errors", Result.SUMTYPE, symbolErrors)

        numSymbolsResult = Result.create(
            "num_symbols", Result.SUMTYPE, numSymbols)

        bitErrorsResult = Result.create("bit_errors",
                                        Result.SUMTYPE, bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits)

        serResult = Result.create(
            "ser", Result.RATIOTYPE, symbolErrors, numSymbols)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        return simResults
Ejemplo n.º 28
0
    def _run_simulation(self, current_parameters):
        # To make sure that this function does not modify the object state,
        # we sobrescibe self to None.
        #self = None

        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        NSymbs = current_parameters["NSymbs"]
        M = current_parameters["M"]
        SNR = current_parameters["SNR"]
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        inputData = np.random.randint(0, M, NSymbs)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        modulatedData = self.modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        noiseVar = 1 / dB2Linear(SNR)
        noise = ((np.random.standard_normal(NSymbs) +
                  1j * np.random.standard_normal(NSymbs)) *
                 np.sqrt(noiseVar / 2))
        receivedData = modulatedData + noise
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate received data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        demodulatedData = self.modulator.demodulate(receivedData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = sum(inputData != demodulatedData)
        bitErrors = misc.count_bit_errors(inputData, demodulatedData)
        numSymbols = inputData.size
        numBits = inputData.size * mod.level2bits(M)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create("symbol_errors", Result.SUMTYPE,
                                           symbolErrors)

        numSymbolsResult = Result.create("num_symbols", Result.SUMTYPE,
                                         numSymbols)

        bitErrorsResult = Result.create("bit_errors", Result.SUMTYPE,
                                        bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits)

        serResult = Result.create("ser", Result.RATIOTYPE, symbolErrors,
                                  numSymbols)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)

        return simResults
Ejemplo n.º 29
0
    def _run_simulation(self,   # pylint: disable=R0914,R0915
                        current_parameters):
        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        M = self.modulator.M
        NSymbs = current_parameters["NSymbs"]
        K = current_parameters["K"]
        Nr = current_parameters["Nr"]
        Nt = current_parameters["Nt"]
        Ns = current_parameters["Ns"]
        SNR = current_parameters["SNR"]

        # Dependent parameters
        noise_var = 1 / dB2Linear(SNR)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calc. precoders and receive filters for IA xxxxxxxxxxxxxxxx
        # We need to perform IA before generating any data so that we know
        # how many streams we need to send (and thus generate data. Note
        # that it is not always equal to Ns. It can be lower for some user
        # if the IA algorithm chooses a precoder that sends zero energy in
        # some stream.
        self.multiUserChannel.randomize(Nr, Nt, K)
        self.multiUserChannel.noise_var = noise_var

        self.ia_solver.clear()
        self.ia_solver.solve(Ns)

        # If any of the Nr, Nt or Ns variables were integers (meaning all
        # users have the same value) we will convert them by numpy arrays
        # with correct size (K).
        # Nr = self.ia_solver.Nr
        # Nt = self.ia_solver.Nt
        Ns = self.ia_solver.Ns

        cumNs = np.cumsum(self.ia_solver.Ns)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # inputData has the data of all users (vertically stacked)
        inputData = np.random.randint(0, M, [np.sum(Ns), NSymbs])
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # modulatedData has the data of all users (vertically stacked)
        modulatedData = self.modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Perform the Interference Alignment xxxxxxxxxxxxxxxxxxx
        # Split the data. transmit_signal will be a list and each element
        # is a numpy array with the data of a user
        transmit_signal = np.split(modulatedData, cumNs[:-1])
        transmit_signal_precoded = map(
            np.dot, self.ia_solver.full_F, transmit_signal)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # noinspection PyProtectedMember
        multi_user_channel = self.ia_solver._multiUserChannel
        # received_data is an array of matrices, one matrix for each receiver.
        received_data = multi_user_channel.corrupt_data(
            transmit_signal_precoded)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Perform the Interference Cancellation xxxxxxxxxxxxxxxxxxxxx
        received_data_no_interference = map(
            np.dot, self.ia_solver.full_W_H, received_data)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        received_data_no_interference = np.vstack(
            received_data_no_interference)
        demodulated_data = self.modulator.demodulate(
            received_data_no_interference)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = np.sum(inputData != demodulated_data)
        bitErrors = misc.count_bit_errors(inputData, demodulated_data)
        numSymbols = inputData.size
        numBits = inputData.size * fundamental.level2bits(M)
        ia_cost = self.ia_solver.get_cost()
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Calculates the Sum Capacity xxxxxxxxxxxxxxxxxxxxxxxxxx
        sirn_all_k = self.ia_solver.calc_SINR()
        calc_capacity = lambda sirn: np.sum(np.log2(1 + sirn))
        # Array with the sum capacity of each user
        sum_capacity = np.array(list(map(calc_capacity, sirn_all_k)))
        # Total sum capacity
        total_sum_capacity = np.sum(sum_capacity)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxxxxxxx Number of iterations of the IA algorithm xxxxxxxxxxxxx
        ia_runned_iterations = self.ia_solver.runned_iterations
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create(
            "symbol_errors", Result.SUMTYPE, symbolErrors)

        numSymbolsResult = Result.create(
            "num_symbols", Result.SUMTYPE, numSymbols)

        bitErrorsResult = Result.create(
            "bit_errors", Result.SUMTYPE, bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits,
                                  accumulate_values=False)

        serResult = Result.create("ser", Result.RATIOTYPE, symbolErrors,
                                  numSymbols, accumulate_values=False)

        ia_costResult = Result.create(
            "ia_cost", Result.RATIOTYPE, ia_cost, 1, accumulate_values=False)

        sum_capacityResult = Result.create(
            "sum_capacity", Result.RATIOTYPE, total_sum_capacity, 1,
            accumulate_values=False)

        ia_runned_iterationsResult = Result.create(
            "ia_runned_iterations", Result.RATIOTYPE, ia_runned_iterations, 1,
            accumulate_values=False)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)
        simResults.add_result(ia_costResult)
        simResults.add_result(sum_capacityResult)
        simResults.add_result(ia_runned_iterationsResult)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        return simResults
Ejemplo n.º 30
0
    def _run_simulation(self, current_parameters):
        """The _run_simulation method is where the actual code to simulate
        the system is.

        The implementation of this method is required by every subclass of
        SimulationRunner.
        """
        # xxxxx Input parameters (set in the constructor) xxxxxxxxxxxxxxxxx
        NSymbs = current_parameters['NSymbs']
        modulator = current_parameters['modulator']
        M = modulator.M
        SNR = current_parameters["SNR"]
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Input Data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        inputData = np.random.randint(0, M, NSymbs)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Modulate input data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        modulatedData = modulator.modulate(inputData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Pass through the channel xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        noiseVar = 1. / dB2Linear(SNR)
        noise = misc.randn_c(NSymbs) * np.sqrt(noiseVar)
        receivedData = modulatedData + noise
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Demodulate received data xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        demodulatedData = modulator.demodulate(receivedData)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Calculates the symbol and bit error rates xxxxxxxxxxxxxxxxx
        symbolErrors = sum(inputData != demodulatedData)
        bitErrors = misc.count_bit_errors(inputData, demodulatedData)
        numSymbols = inputData.size
        numBits = inputData.size * fundamental.level2bits(M)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # xxxxx Return the simulation results xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        symbolErrorsResult = Result.create("symbol_errors", Result.SUMTYPE,
                                           symbolErrors)

        numSymbolsResult = Result.create("num_symbols", Result.SUMTYPE,
                                         numSymbols)

        bitErrorsResult = Result.create("bit_errors", Result.SUMTYPE, bitErrors)

        numBitsResult = Result.create("num_bits", Result.SUMTYPE, numBits)

        berResult = Result.create("ber", Result.RATIOTYPE, bitErrors, numBits)

        serResult = Result.create("ser", Result.RATIOTYPE, symbolErrors,
                                  numSymbols)

        simResults = SimulationResults()
        simResults.add_result(symbolErrorsResult)
        simResults.add_result(numSymbolsResult)
        simResults.add_result(bitErrorsResult)
        simResults.add_result(numBitsResult)
        simResults.add_result(berResult)
        simResults.add_result(serResult)
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        return simResults
Ejemplo n.º 31
0
Pe_dBm = -10000  # transmit power (in dBm) of the ext. interference
ext_int_rank = 1  # Rank of the external interference

# xxxxxxxxxx General Parameters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
rep_max = 20000  # Maximum number of repetitions for each

pbar = progressbar.ProgressbarText(
    rep_max, message="Simulating for SNR: {0}".format(SNR_dB))

# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxx Dependent parameters (don't change these) xxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Path loss (in linear scale) from the cell center to
path_loss_border = path_loss_obj.calc_path_loss(cell_radius)
noise_var = conversion.dBm2Linear(N0_dBm)
snr = conversion.dB2Linear(SNR_dB)
transmit_power = snr * noise_var / path_loss_border
# External interference power
pe = conversion.dBm2Linear(Pe_dBm)

# Cell Grid
cell_grid = cell.Grid()
cell_grid.create_clusters(num_clusters, num_cells, cell_radius)
# noinspection PyProtectedMember
cluster0 = cell_grid._clusters[0]
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# xxxxxxxxxx Create the scenario xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
cell_ids = np.arange(1, num_cells + 1)
Ejemplo n.º 32
0
def main():
    """Main function.
    """
    K = 3
    Nr = 4
    Nt = 4
    Ns = 2
    SNR = 30.0
    P = 1.0

    # Dependent parameters
    noise_var = 1 / dB2Linear(SNR)

    RepMax = 1
    mmse_sinrs = np.empty([RepMax, K, Ns], dtype=float)
    max_sinr_sinrs = np.empty([RepMax, K, Ns], dtype=float)
    mmse_capacity = np.empty(RepMax, dtype=float)
    max_sinr_capacity = np.empty(RepMax, dtype=float)

    pbar = ProgressbarText(RepMax, message="Simulating for SNR: {0}".format(SNR))

    for rep in range(RepMax):
        # Creat the channel
        multiUserChannel = pyphysim.channels.multiuser.MultiUserChannelMatrix()
        multiUserChannel.randomize(Nr, Nt, K)
        multiUserChannel.noise_var = noise_var

        # Creat the IA solver object
        mmse_ia_solver = algorithms.MMSEIASolver(multiUserChannel)
        max_sinr_ia_solver = algorithms.MaxSinrIASolver(multiUserChannel)

        mmse_ia_solver.randomizeF(Ns, P)

        mmse_ia_solver.initialize_with = 'fix'
        max_sinr_ia_solver.initialize_with = 'fix'
        # noinspection PyProtectedMember
        max_sinr_ia_solver._F = mmse_ia_solver._F

        #mmse_ia_solver.initialize_with = 'fix'

        # We wouldn't need to explicitly set ia_solver.noise_var
        # variable if the multiUserChannel object had the correct value at
        # this point.
        # mmse_ia_solver.noise_var = noise_var
        mmse_ia_solver.max_iterations = 200
        mmse_ia_solver.solve(Ns)

        # max_sinr_ia_solver.noise_var = noise_var
        max_sinr_ia_solver.max_iterations = 200

        max_sinr_ia_solver.solve(Ns)

        mmse_sinrs[rep] = list(map(linear2dB, mmse_ia_solver.calc_SINR()))
        max_sinr_sinrs[rep] = list(map(linear2dB, max_sinr_ia_solver.calc_SINR()))

        mmse_capacity[rep] = np.sum(calc_capacity(mmse_ia_solver.calc_SINR()))
        max_sinr_capacity[rep] = np.sum(calc_capacity(max_sinr_ia_solver.calc_SINR()))

        # print "MMSE Alt. SINRs:\n{0}".format(np.vstack(mmse_sinrs[rep]))
        # print "Max SINR Alg. SINRs:\n{0}".format(np.vstack(max_sinr_sinrs[rep]))

        # print "MMSE Alt. Capacity: {0}".format(np.sum(calc_capacity(mmse_sinrs[rep])))
        # print "Max SINR Alg. Capacity: {0}".format(np.sum(calc_capacity(max_sinr_sinrs[rep])))
        # print

        pbar.progress(rep)

    print("MMSE Average SINRs:\n{0}".format(mmse_sinrs.mean(0)))
    print("Max SINR Average SINRs:\n{0}".format(max_sinr_sinrs.mean(0)))
    print("MMSE Average Capacity: {0}".format(mmse_capacity.mean()))
    print("Max SINR Average Capacity: {0}".format(max_sinr_capacity.mean()))

    print("\nEnd!")
Ejemplo n.º 33
0
 def test_dB2Linear(self):
     self.assertAlmostEqual(conversion.dB2Linear(30), 1000.0)
Ejemplo n.º 34
0
def perform_simulation(scenario_params, power_params, plot_results_bool=True):  # pylint: disable=R0914
    """
    Run the simulation.
    """
    # xxxxxxxxxx Simulation Scenario Configuration xxxxxxxxxxxxxxxxxxxxxxxx
    # The size of the side of each square room
    side_length = scenario_params["side_length"]
    # How much (in dB) is lost for each wall teh signal has to pass
    single_wall_loss_dB = scenario_params["single_wall_loss_dB"]

    # Square of 12 x 12 square rooms
    num_rooms_per_side = scenario_params["num_rooms_per_side"]
    # Total number of rooms in the grid
    num_rooms = num_rooms_per_side ** 2

    # 1 means 1 ap every room. 2 means 1 ap every 2 rooms and so on. Valid
    # values are: 1, 2, 4 and 9.
    ap_decimation = scenario_params["ap_decimation"]
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Simulation Power Configuration xxxxxxxxxxxxxxxxxxxxxxxxxxx
    # Transmit power of each access point
    Pt_dBm = power_params["Pt_dBm"]
    noise_power_dBm = power_params["noise_power_dBm"]

    Pt = dBm2Linear(Pt_dBm)  # 20 dBm transmit power
    noise_var = dBm2Linear(noise_power_dBm)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the positions of all rooms xxxxxxxxxxxxxxxxxxxxx
    room_positions = calc_room_positions_square(side_length, num_rooms)
    room_positions.shape = (num_rooms_per_side, num_rooms_per_side)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Create the path loss object xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    pl_metis_ps7_obj = pathloss.PathLossMetisPS7()
    pl_metis_ps7_obj.handle_small_distances_bool = True
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Add users in random positions in the 2D grid xxxxxxxxxxxxx
    num_users = 100  # We will create this many users in the 2D grid
    users_positions = (
        num_rooms_per_side
        * side_length
        * (np.random.random_sample(num_users) + 1j * np.random.random_sample(num_users) - 0.5 - 0.5j)
    )
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx AP Allocation xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # 1 AP in each room
    ap_positions = get_ap_positions(room_positions, ap_decimation)
    num_aps = ap_positions.size
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate distances: each user to each AP xxxxxxxxxxxxxxxx
    # Dimension: (num_users, num_APs)
    dists_m = np.abs(users_positions[:, np.newaxis] - ap_positions[np.newaxis, :])
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Calculate AP association xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # INPUTS
    # Find in which room each user is
    users_rooms = np.argmin(np.abs(room_positions.reshape([-1, 1]) - users_positions[np.newaxis, :]), axis=0)

    # Number of walls from each room to each other room
    num_walls_all_rooms = calc_num_walls(side_length, room_positions, ap_positions)
    # Number of walls from each room that has at least one user to each
    # room with an AP
    num_walls_rooms_with_users = num_walls_all_rooms[users_rooms]

    # Path loss from each user to each AP (no matter if it will be a
    # transmitting AP or not, since we still have to perform the AP
    # association)
    pl_all = pl_metis_ps7_obj.calc_path_loss(dists_m, num_walls=num_walls_rooms_with_users)

    # Calculate wall losses from each user to each AP (no matter if it will
    # be a transmitting AP or not, since we still have to perform the AP
    # association)
    wall_losses_dB_all = num_walls_rooms_with_users * single_wall_loss_dB

    # Calculate path loss plus wall losses (we multiply the linear values)
    # from each user to each AP (no matter if it will be a transmitting AP
    # or not, since we still have to perform the AP association)
    pl_all_plus_wl = pl_all * dB2Linear(-wall_losses_dB_all)

    # OUTPUTS
    # Determine with which AP each user is associated with.
    # Each user will associate with the CLOSEST access point.
    ap_assoc = find_ap_assoc_best_channel(pl_all_plus_wl)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Find which Access Points should stay on xxxxxxxxxxxxxxxxxx
    # Indexes of the active APs
    transmitting_aps, users_count = np.unique(ap_assoc, return_counts=True)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the SINRs for each path loss model xxxxxxxxxxxxx
    # Take the path loss plus wall losses only for the transmitting aps
    pl_all_plus_wall_losses_tx_aps = pl_all_plus_wl.take(transmitting_aps, axis=1)
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxx Calculate the SINRs and capacity xxxxxxxxxxxxxxxxxxxxxxxxx
    sinr_array_pl_metis_ps7_dB, capacity_metis_ps7 = simulate_for_a_given_ap_assoc(
        pl_all_plus_wall_losses_tx_aps, ap_assoc, transmitting_aps, Pt, noise_var
    )
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Plot the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    if plot_results_bool is True:
        print(
            ("\nMin/Mean/Max SINR value (METIS PS7):" "\n    {0}\n    {1}\n    {2}").format(
                sinr_array_pl_metis_ps7_dB.min(), sinr_array_pl_metis_ps7_dB.mean(), sinr_array_pl_metis_ps7_dB.max()
            )
        )

        print(
            ("\nMin/Mean/Max Capacity value (METIS PS7):" "\n    {0}\n    {1}\n    {2}").format(
                capacity_metis_ps7.min(), capacity_metis_ps7.mean(), capacity_metis_ps7.max()
            )
        )

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # xxxxxxxxxxxxxxx Plot the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        # Create a mask for the active APs
        transmitting_aps_mask = np.zeros(num_aps, dtype=bool)
        transmitting_aps_mask[transmitting_aps] = True

        # Save how many users are associated with each AP
        users_per_ap = np.zeros(num_aps, dtype=int)
        users_per_ap[transmitting_aps_mask] = users_count

        # xxxxxxxxxx Plot all rooms and users xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        all_rooms = [
            shapes.Rectangle(
                pos - side_length / 2.0 - side_length * 1j / 2.0, pos + side_length / 2.0 + side_length * 1j / 2.0
            )
            for pos in room_positions.flatten()
        ]

        # Plot all Rooms and save the axis where they were plotted
        plt.figure(figsize=(10, 10))
        gs = gridspec.GridSpec(2, 1, height_ratios=[4, 1])
        # ax1 is where we will plot everything
        ax1 = plt.subplot(gs[0])
        ax1.set_xlabel("Position X coordinate")
        ax1.set_ylabel("Position Y coordinate")
        ax1.set_title("Plot of all Rooms")
        ax1.set_ylim([-60, 60])
        ax1.set_xlim([-60, 60])
        ax1 = plot_all_rooms(all_rooms, ax1)
        ax1.hold(True)

        # ax2 will be used for annotations
        ax2 = plt.subplot(gs[1])
        plt.setp(ax2.get_xticklabels(), visible=False)
        plt.setp(ax2.get_yticklabels(), visible=False)
        ax2.set_ylim([0, 10])
        ax2.set_xlim([0, 10])
        details = ax2.text(
            5, 5, "Details", verticalalignment="center", horizontalalignment="center", family="monospace"
        )

        # Set the an array with colors for the access points. Transmitting APs
        # will be blue, while inactive APs will be gray
        ap_colors = np.empty(ap_positions.shape, dtype="U4")
        ap_colors[transmitting_aps_mask] = "b"
        ap_colors[np.logical_not(transmitting_aps_mask)] = "gray"

        # Plot the access points. We set linewidth to 0.0 so that there is no
        # border. We set the size ('s' keyword) to 50 to make it larger. The
        # colors are set according to the ap_colors array.
        # Note that we set a 5 points tolerance for the pick event.
        aps_plt = ax1.scatter(
            ap_positions.real, ap_positions.imag, marker="^", c=ap_colors, linewidths=0.1, s=50, picker=3
        )

        # Plot the users
        # Note that we set a 5 points tolerance for the pick event.
        users_plt = ax1.scatter(
            users_positions.real, users_positions.imag, marker="*", c="r", linewidth=0.1, s=50, picker=3
        )

        # xxxxxxxxxx Define a function to call for the pick_event Circle used
        # to select an AP. We will set its visibility to False here. When an AP
        # is selected, we move this circle to its position and set its
        # visibility to True.
        selected_ap_circle = ax1.plot([0], [0], "o", ms=12, alpha=0.4, color="yellow", visible=False)[0]

        # Define the callback function for the pick event
        def on_pick(event):
            """Callback for the pick event in the matplotlib plot."""
            # We will reset users colors on each pick
            users_colors = np.empty(ap_assoc.size, dtype="U1")
            users_colors[:] = "r"

            # Index of the point clicked
            ind = event.ind[0]

            if event.artist == aps_plt:
                # Disable the circle in the AP
                selected_ap_circle.set_visible(False)

                if ind not in ap_assoc:
                    # Text information for the disabled AP
                    text = "AP {0} (Disabled)".format(ind)
                else:
                    # Text information for the selected AP
                    text = "AP {0} with {1} user(s)\nTotal throughput: {2:7.4f}"
                    text = text.format(ind, users_per_ap[ind], np.sum(capacity_metis_ps7[ap_assoc == ind]))

                    # Change the colors of the users associated with the
                    # current AP to green
                    users_colors[ap_assoc == ind] = "g"

            elif event.artist == users_plt:
                # Text information for the selected user
                text = "User {0}\n    SINR: {1:7.4f}\nCapacity: {2:7.4f}".format(
                    ind, sinr_array_pl_metis_ps7_dB[ind], capacity_metis_ps7[ind]
                )

                # If there other users are associated with the same AP of the
                # current user
                if users_per_ap[ap_assoc[ind]] > 1:
                    text = "{0}\nShares AP with {1} other user(s)".format(text, users_per_ap[ap_assoc[ind]] - 1)

                users_AP = ap_assoc[ind]
                # Plot a yellow circle in the user's AP
                ap_pos = ap_positions[users_AP]
                # CHange the collor of other users in the same AP to green and
                # the current user to cyan
                users_colors[ap_assoc == users_AP] = "g"
                users_colors[ind] = "c"

                selected_ap_circle.set_visible(True)
                selected_ap_circle.set_data([ap_pos.real], [ap_pos.imag])

            # Set users colors
            users_plt.set_color(users_colors)

            # Set the details text
            details.set_text(text)
            ax1.figure.canvas.draw()

        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

        # Connect the on_pick function with the pick event
        ax1.figure.canvas.mpl_connect("pick_event", on_pick)

        plt.show()
        # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxx Return the results xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    return sinr_array_pl_metis_ps7_dB, capacity_metis_ps7