pyphysim.comm package

Submodules

pyphysim.comm.blockdiagonalization module

Module implementing the block diagonalization algorithm.

There are two ways to use this module. You can either use the BlockDiagonalizer class, or you can use the block_diagonalize() and the calc_receive_filter() functions (which use the BlockDiagonalizer class in their implementation).

class pyphysim.comm.blockdiagonalization.BDWithExtIntBase(num_users: int, iPu: float, noise_var: float, pe: float)[source]

Bases: pyphysim.comm.blockdiagonalization.BlockDiagonalizer

Class to perform the block diagonalization algorithm in a joint transmission scenario taking into account the external interference.

This is the base class for any block diagonalization class that takes into account the external interference.

Parameters
  • num_users (int) – Number of users.

  • iPu (float) – Power available for EACH user (in linear scale).

  • noise_var (float) – Noise variance (power in linear scale).

  • pe (float) – Power of the external interference source (in linear scale)

calc_whitening_matrices(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → List[numpy.ndarray][source]

Calculates the whitening receive filters for each user.

Note that to consider the noise variance it must be set in the provided mu_channel object.

Parameters

mu_channel (MultiUserChannelMatrixExtInt) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as th external interference.

Returns

W_all_k – The whitening matrices that each receiver should use to whiten the external interference. Each element in W_all_k is the whitening filter (with the conjugate transpose already applied) for a receiver.

Return type

list[np.ndarray]

class pyphysim.comm.blockdiagonalization.BlockDiagonalizer(num_users: int, iPu: float, noise_var: float)[source]

Bases: object

Class to perform the block diagonalization algorithm in a joint transmission scenario.

In the block diagonalization algorithm either a single base station with more antennas transmits for multiple users at the same time or a group of base stations acts as a single transmitter to send data to the multiple users at the same time. In both cases the block diagonalization algorithm assures that each receiver does not see interference from the other receivers.

The water-filling algorithm is also applied to optimally distribute the power. However, in the case with multiple base stations, the power restriction in each base station must be respected. Therefore, after the power is optimally allocated at each base station all powers will be normalized to respect the power restriction of the base transmitting the highest energy. This is what is done in the block_diagonalize() method.

If the power should not be optimally allocated with the water-filling algorithm, use the block_diagonalize_no_waterfilling() method instead. The power restriction in each base station will still be respected, but the base station will equally divide its power among the available dimensions. Note that the result will be similar to block_diagonalize() in the high SNR regime.

Parameters
  • num_users (int) – Number of users.

  • iPu (float) – Power available for EACH user.

  • noise_var (float) – Noise variance (power in linear scale).

Examples

Consider the case where we have 3 base station (BSs) jointly transmitting to 3 users, where each base station has a power of 1.5, the number of antennas (at each BS and at each receiver) is 2, and the noise variance is 1e-4. The channel can be block diagonalized for this scenario with

>>> bs_power = 1.5
>>> noise_var = 1e-4
>>> num_users = 2
>>> Ntx = 2  # Number of transmit antennas (per BS)
>>> Nrx = 2  # Number of receive antennas (per user)
>>> # Create the BlockDiagonalizer object
>>> bd = BlockDiagonalizer(num_users, bs_power, noise_var)
>>> channel = np.array([[-0.9834-0.0123j,  0.6503-0.3189j,      0.5484+1.7049j, -1.0891-0.1025j], [-0.5911-0.3055j, -0.6205+0.3375j,     -0.7995+0.3723j,  0.7412-1.2537j], [-0.2732+0.475j , -0.4191+0.4019j,     0.1047-0.5592j,  0.7548-1.0214j], [ 0.5377-0.208j , -0.1480-1.0527j,     -0.6373+0.4081j, -0.5854-0.8135j]])
>>> (newH, Ms) = bd.block_diagonalize(channel)

We can see that the equivalent channel (after applying the Ms modulation matrix) is really block diagonalized.

>>> print(np.round(newH + 1e-10 + 1e-10j, 4))
[[ 0.0916+0.0135j -1.7449-0.4328j  0.    +0.j      0.    +0.j    ]
 [-0.0114-0.146j   0.0213-1.1366j  0.    +0.j      0.    +0.j    ]
 [ 0.    +0.j      0.    +0.j      0.0868+0.1565j -0.3673+0.2289j]
 [ 0.    +0.j      0.    +0.j     -0.0396+0.0407j  1.024 +0.8997j]]

Notice how the power restriction of each BS is respected (although only one BS will transmit with its maximum power).

>>> print(np.round(np.linalg.norm(Ms[:,0:Ntx])**2, 4))
1.4997
>>> print(np.round(np.linalg.norm(Ms[:,Ntx:])**2, 4))
1.5

Notes

The block diagonalization algorithm is described in [Spencer2004], where different power allocations are illustrated. The BlockDiagonalizer class implement two power allocation methods, a global power allocation, and a ‘per transmitter’ power allocation.

_calc_BD_matrix_no_power_scaling(mtChannel: numpy.ndarray) → Tuple[numpy.ndarray, numpy.ndarray][source]

Calculates the modulation matrix “M” that block diagonalizes the channel mtChannel, but without any king of power scaling.

The “modulation matrix” is a matrix that changes the channel to a block diagonal structure and it is the first part in the Block Diagonalization algorithm. The returned modulation matrix is equivalent to Equation (12) of [Spencer2004] but without the power scaling matrix \(\Lambda\). Therefore, for the complete BD algorithm it is still necessary to perform this power scaling in the output of _calc_BD_matrix_no_power_scaling.

Parameters

mtChannel (np.ndarray) – Channel from the transmitter to all users.

Returns

(Ms_bad, Sigma) – The modulation matrix “Ms_bad” is a precoder that block diagonalizes the channel. The singular values of the equivalent channel when the modulation matrix is applied correspond to Sigma. Therefore, Sigma can be used latter in the power allocation process.

Return type

(np.ndarray,np.ndarray)

Notes

The reason why the Block Diagonalization algorithm was broken down into the code here and the power scaling code is because the power scaling may changing depending on the scenario. For instance, if the transmitter corresponds to a single base station the the power may be distributed into all the dimensions of the Modulation matrix. On the other hand, if the transmitter corresponds to multiple base stations jointly transmitting to multiple users then the power of each base station must be distributed only into the dimensions corresponding to that base station.

_get_sub_channel(mt_channel: numpy.ndarray, desired_users: Union[int, Iterable[int]])numpy.ndarray[source]

Get a subchannel according to the desired_users vector.

Parameters
  • mt_channel (np.ndarray) – Channel of all users (2D numpy array).

  • desired_users (list[int]) – An iterable with the indexes of the desired users or an integer.

Returns

mtSubmatrix – Submatrix of the desired users (2D numpy array)

Return type

np.ndarray

Notes

As an example, let’s consider the case with a channel for 3 receivers, each with 2 receive antennas, where the transmitter has 6 transmit antennas.

>>> BD = BlockDiagonalizer(3, 0, 0)
>>> channel = np.vstack([np.ones([2, 6]), 2 * np.ones([2, 6]),                                 3 * np.ones([2, 6])])
>>> BD._get_sub_channel(channel, [0,2])
array([[1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1.],
       [3., 3., 3., 3., 3., 3.],
       [3., 3., 3., 3., 3., 3.]])
>>> BD._get_sub_channel(channel, 0)
array([[1., 1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1., 1.]])
_get_tilde_channel(mtChannel: numpy.ndarray, user: int)numpy.ndarray[source]

Return the combined channel of all users except user.

Let $k$ be the index for user. If the channel from all transmitters to receiver $k$ is $mtH_k$, then this method returns $tilde{mtH_k} = [mtH_1^T, ldots, mtH_{k-1}^T, mtH_{k+1}^T, ldots, mtH_K]^T$.

Parameters
  • mtChannel (np.ndarray) – Channel of all users (2D numpy array).

  • user (int) – Index of the user.

Returns

The combined channel of all users except user.

Return type

np.ndarray

_perform_global_waterfilling_power_scaling(Ms_bad: numpy.ndarray, Sigma: numpy.ndarray)numpy.ndarray[source]

Perform the power scaling based on the water-filling algorithm for all the parallel channel gains in Sigma.

This power scaling method corresponds to maximizing the sum rate when the transmitter is a single base station transmitting to all users. Note that this approach may result in one or two “strong users” taking a dominant share of the available power.

Parameters
  • Ms_bad (np.ndarray) – The previously calculated modulation matrix (without any power scaling). This should be a 2D numpy array.

  • Sigma (np.ndarray) – The singular values of the effective channel when Ms_bad is applied. This should be a 1D numpy array of positive floats.

Returns

Ms_good – The modulation matrix (2D numpy array) with the global power scaling applied.

Return type

np.ndarray

_perform_normalized_waterfilling_power_scaling(Ms_bad: numpy.ndarray, Sigma: numpy.ndarray)numpy.ndarray[source]

Perform the power scaling based on the water-filling algorithm for all the parallel channel gains in Sigma, but normalize the result by the power of the base station transmitting with the highest power.

When we have a joint transmission where multiple base stations act as a single base station, then performing the water-filling on all the channels for the total available power may result in some base station transmitting with a higher power then it actually can. Therefore, we normalize the power of the strongest BS so that the power restriction at each BS is satisfied. This is sub-optimal since the other BSs will use less power then available, but it is simple and it works.

Parameters
  • Ms_bad (np.ndarray) – The previously calculated modulation matrix (without any power scaling)

  • Sigma (np.ndarray) – The singular values of the effective channel when Ms_bad is applied. This should be a 1D numpy array with positive values.

Returns

Ms_good – The modulation matrix with the normalized power scaling applied. This is a 2D numpy array.

Return type

np.ndarray

block_diagonalize(mtChannel: numpy.ndarray) → Tuple[numpy.ndarray, numpy.ndarray][source]

Perform the block diagonalization.

mtChannel is a matrix with the channel from the transmitter to all users, where each iNUsers rows correspond to one user.

For an example, see the documentation of the BlockDiagonalizer class.

Parameters

mtChannel (np.ndarray) – Channel from (all) the transmitter(s) to all users. This should be a 2D numpy array.

Returns

newH is a 2D numpy array corresponding to the Block diagonalized channel, while Ms_good is a 2D numpy array corresponding to the precoder matrix used to block diagonalize the channel.

Return type

np.ndarray, np.ndarray

block_diagonalize_no_waterfilling(mtChannel: numpy.ndarray) → Tuple[numpy.ndarray, numpy.ndarray][source]

Performs the block diagonalization, but without applying the water-filling algorithm.

The power of each base station is equally divided such that the square of the Frobenius norm or the columns of Ms_good corresponding to that base station is equal to its power.

Parameters

mtChannel (np.ndarray) – Channel from (all) the transmitter(s) to all users. This should be a 2D numpy array.

Returns

(newH, Ms_good) – newH is a 2D numpy array corresponding to the Block diagonalized channel, while Ms_good is a 2D numpy array corresponding to the precoder matrix used to block diagonalize the channel.

Return type

(np.ndarray,np.ndarray)

static calc_receive_filter(newH: numpy.ndarray)numpy.ndarray[source]

Calculates the Zero-Forcing receive filter.

Parameters

newH (np.ndarray) – The block diagonalized channel (2D numpy array).

Returns

W_bd – The zero-forcing matrix (2D numpy array) to separate each stream of each user.

Return type

np.ndarray

class pyphysim.comm.blockdiagonalization.EnhancedBD(num_users: int, iPu: float, noise_var: float, pe: float)[source]

Bases: pyphysim.comm.blockdiagonalization.BDWithExtIntBase

Class to perform the block diagonalization algorithm in a joint transmission scenario taking into account the external interference.

The EnhancedBD class performs the block diagonalization characteristic to the joint transmission scenario where multiple base stations act as a single transmitter to send data to the users. However, in addition to what the BlockDiagonalizer class does the EnhancedBD class can also take external interference into account.

One way to reduce of eliminate the external interference is to sacrifice streams in directions strongly occupied by the external interference.

Parameters
  • num_users (int) – Number of users.

  • iPu (float) – Power available for EACH user (in linear scale).

  • noise_var (float) – Noise variance (power in linear scale).

  • pe (float) – Power of the external interference source (in linear scale)

Notes

See the BlockDiagonalizer class for details about the block diagonalization process.

static _calc_linear_SINRs(Heq_k_red: numpy.ndarray, Wk: numpy.ndarray, Re_k: numpy.ndarray)numpy.ndarray[source]

Calculates the effective SINRs of each parallel channel.

Parameters
  • Heq_k_red (np.ndarray) – Equivalent channel matrix of user k including the block diagonalization and any stream reduction applied (2D numpy array).

  • Wk (np.ndarray) – Receive filter for user k (2D numpy array).

  • Re_k (np.ndarray) – A numpy array where each element is the covariance matrix of the external interference PLUS noise seen by a user (1D numpy array of 2D numpy arrays.).

Returns

sinrs – SINR (in linear scale) of all the parallel channels of all users.

Return type

np.ndarray

_perform_BD_no_waterfilling_decide_number_streams(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray][source]

Function called inside perform_BD_no_waterfilling when the stream reduction is performed and the number of sacrificed streams depend on the metric used (the function set as self._metric_func).

Parameters

mu_channel (MultiUserChannelMatrixExtInt) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as th external interference.

Returns

  • MsPk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the precoder for a user (1D numpy array of 2D numpy arrays).

  • Wk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the receive filter for a user (1D numpy array of 2D numpy arrays).

  • Ns_all_users (np.ndarray) – Number of streams of each user (1D numpy array of ints).

_perform_BD_no_waterfilling_fixed_or_naive_reduction(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray][source]

Function called inside perform_BD_no_waterfilling when the naive or the fixed stream reduction should be performed.

For the naive or the fixed stream reduction cases the number of transmitted streams is always equal to self._metric_func_extra_args[‘num_streams’]. That is, the number of sacrificed streams is equal to the number of transmit antennas minus num_streams.

The only difference between the naive and the fixed cases is that in the fixed case the reduction matrix P is chosen so that it gets as orthogonal to the external interference as possible, while the naive case simple chooses P as a submatrix of the diagonal matrix.

Parameters

mu_channel (MultiUserChannelMatrixExtInt) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as th external interference.

Returns

  • MsPk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the precoder for a user (1D numpy array of 2D numpy arrays).

  • Wk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the receive filter for a user (1D numpy array of 2D numpy arrays).

  • Ns_all_users (np.ndarray) – Number of streams of each user (1D numpy array of ints).

_perform_BD_no_waterfilling_no_stream_reduction(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray][source]

Function called inside perform_BD_no_waterfilling when no stream reduction should be performed.

Parameters

mu_channel (MultiUserChannelMatrixExtInt) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as th external interference.

Returns

  • MsPk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the precoder for a user (1D numpy array of 2D numpy arrays).

  • Wk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the receive filter for a user (1D numpy array of 2D numpy arrays).

  • Ns_all_users (np.ndarray) – Number of streams of each user (1D numpy array of ints).

block_diagonalize_no_waterfilling(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray][source]

Perform the block diagonalization of mu_channel taking the external interference into account.

This is the main method calculating the BD algorithm. Two important parameters used here are the noise variance (an attribute of the mu_channel object) and the external interference power (the pe attribute) attributes.

Parameters

mu_channel (MultiUserChannelMatrixExtInt object.) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as the external interference.

Returns

  • MsPk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the precoder for a user (1D numpy array of 2D numpy arrays).

  • Wk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the receive filter for a user (1D numpy array of 2D numpy arrays).

  • Ns_all_users (np.ndarray) – Number of streams of each user (1D numpy array of ints).

static calc_receive_filter_user_k(Heq_k_P: numpy.ndarray, P: Optional[numpy.ndarray] = None)numpy.ndarray[source]

Calculates the Zero-Forcing receive filter of a single user k with or without the stream reduction.

Parameters
  • Heq_k_P (np.ndarray) – The equivalent channel of user k after the block diagonalization process and any stream reduction (2D numpy array).

  • P (np.ndarray, optional) – P has the most significant singular vectors of the external interference plus noise covariance matrix for each receiver.

Returns

W – The receive filter of user k (2D numpy array).

Return type

np.ndarray

Notes

If P is not None then the number of transmit streams will be equal to the number of columns in P. Also, the receive filter W includes a projection into the subspace spanned by the columns of P. Since P was calculated to be in the directions with weaker (or no) external interference then the receive filter W will mitigate the external interference.

property metric_name

Get name of the method used to decide how many streams to sacrifice.

Returns

The metric name.

Return type

str

set_ext_int_handling_metric(metric: Optional[str], metric_func_extra_args_dict: Optional[Dict[str, Any]] = None)None[source]

Set the metric used to decide how many streams to sacrifice for external interference handling.

The modification to the standard Block Diagonalization algorithm performed in this class consists in avoid transmit data in the subspace strongly occupied by the external interference source.

This sacrificing (not transmitting) of streams may or may not be worth it and different metrics can be used to decide this.

The valid values for the metric argument are ‘None’ (python None object), “fixed”, “naive”, “capacity” and “effective_throughput”. Each of these values will impact on how the number of transmit streams is chosen and which subspace is actually used for the desired signal.

For the “fixed” and “naive” metrics, the number of transmit streams is determined by the value of the ‘num_streams’ key in the metric_func_extra_args_dict. The difference between them is how the subspace where the useful data is determined (for the given number of sacrificed streams).

For the “naive” metric, the stream reduction is performed by multiplying the usual block diagonalizing matrix M by a subset of the identity matrix. For the “fixed” metric the subspace containing the lowest remaining external interference energy is chosen by multiplying the block diagonalizing matrix M by the singular vectors of the external interference covariance matrix corresponding to the lowest singular values. The same procedure is used for the other metrics.

Differently from the “naive” and “fixed” metrics, the “capacity” and “effective_throughput” metrics try to determine this best number of sacrificed streams.

  • If metric is None, then all streams will be used. That is, no streams will be sacrificed and the external interference won’t be mitigated.

  • If metric is “None” or “naive” then the specified number of streams will be used.

  • If metric is ‘capacity’, then the metric used to decide how many streams to sacrifice will be the sum capacity. The function calc_shannon_sum_capacity() will be used to calculate the sum capacity metric, and since it only uses the SINR values, no extra arguments are required in the metric_func_extra_args_dict dictionary.

  • If metric is ‘effective_throughput’ then the metric used to decide how many streams to sacrifice will be the effective throughput that can be obtained. The function _calc_effective_throughput will be used to calculate the effective throughput. Since it requires the a modulator and a packet length you should set the metric_func_extra_args_dict so that it has the keys ‘modulator’ and ‘packet_length’ with the correct values (a modulator object and an integer, respectively)

Parameters
  • metric (str | None) – The metric name. Must be one of the available metrics: {None, ‘capacity’, ‘effective_throughput’}.

  • metric_func_extra_args_dict (dict) – A dictionary containing the extra arguments that must be passed to the metric function. For the “naive” and “fixed” metrics, this dictionary must contain the “num_streams” keyword with the desired number of transmit streams. For the “effective_throughput” metric this dictionary mst contain the “modulator” and “packet_length” keywords with a modulator object and an integer, respectively. For the other metrics metric_func_extra_args_dict will be ignored.

Raises

AttributeError – If the metric is not one of the available metrics or if the metric_func_extra_args_dict does not contain the required keywords.

class pyphysim.comm.blockdiagonalization.WhiteningBD(num_users: int, iPu: float, noise_var: float, pe: float)[source]

Bases: pyphysim.comm.blockdiagonalization.BDWithExtIntBase

Class to perform the block diagonalization algorithm in a joint transmission scenario taking into account the external interference.

Parameters
  • num_users (int) – Number of users.

  • iPu (float) – Power available for EACH user (in linear scale).

  • noise_var (float) – Noise variance (power in linear scale).

  • pe (float) – Power of the external interference source (in linear scale)

static _calc_receive_filter_with_whitening(newH: numpy.ndarray, whitening_filter: numpy.ndarray, Nr: numpy.ndarray, Nt: numpy.ndarray)numpy.ndarray[source]

Calculates the Zero-Forcing receive filter of all users.

Parameters
  • newH (np.ndarray) – The block diagonalized channel (with the whitening applied). This should be a 2D numpy array.

  • whitening_filter (np.ndarray) – The whitening filter of all users. This is a block diagonal matrix where each “block” is the whitening filter of a user.

  • Nr (np.ndarray) – The number of receive antennas of each user.

  • Nt (np.ndarray) – The number of transmit antennas of each user.

Returns

Wk_all_users – A 1D numpy array where each element corresponds to the receive filter for a user. This is a 1D numpy array of 2D numpy arrays.

Return type

np.ndarray

block_diagonalize_no_waterfilling(mu_channel: pyphysim.channels.multiuser.MultiUserChannelMatrixExtInt) → Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray][source]

Perform the block diagonalization of mu_channel taking the external interference into account.

Parameters

mu_channel (MultiUserChannelMatrixExtInt) – A MultiUserChannelMatrixExtInt object, which has the channel from all the transmitters to all the receivers, as well as the external interference.

Returns

  • Ms_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the precoder for a user (1D numpy array of 2D numpy arrays).

  • Wk_all_users (np.ndarray) – A 1D numpy array where each element corresponds to the receive filter for a user (1D numpy array of 2D numpy arrays).

  • Ns_all_users (np.ndarray) – Number of streams of each user (1D numpy array of ints).

pyphysim.comm.blockdiagonalization.block_diagonalize(mtChannel: numpy.ndarray, num_users: int, iPu: float, noise_var: float) → Tuple[numpy.ndarray, numpy.ndarray][source]

Performs the block diagonalization of mtChannel.

Parameters
  • mtChannel (np.ndarray) – Global channel matrix (a 2D numpy array).

  • num_users (int) – Number of users

  • iPu (float) – Power available for each user

  • noise_var (float) – Noise variance

Returns

(newH, Ms_good) – newH is a 2D numpy array corresponding to the Block diagonalized channel, while Ms_good is a 2D numpy array corresponding to the precoder matrix used to block diagonalize the channel.

Return type

(np.ndarray,np.ndarray)

Notes

The block diagonalization algorithm is described in [Spencer2004], where different power allocations are illustrated. The BlockDiagonalizer class implement two power allocation methods, a global power allocation, and a ‘per transmitter’ power allocation.

pyphysim.comm.blockdiagonalization.calc_receive_filter(newH: numpy.ndarray)numpy.ndarray[source]

Calculates the Zero-Forcing receive filter.

Parameters

newH (np.ndarray) – The block diagonalized channel.

Returns

The zero-forcing matrix to separate each stream of each user. Note that W_bd_H is directly applied to the received signals (no need to calculate the conjugate transpose).

Return type

np.ndarray

pyphysim.comm.waterfilling module

Implements a waterfilling method.

The doWF method performs the waterfilling algorithm.

pyphysim.comm.waterfilling.doWF(vtChannels: numpy.ndarray, dPt: float, noiseVar: float = 1.0, Es: float = 1.0) → Tuple[numpy.ndarray, float][source]

Performs the Waterfilling algorithm and returns the optimum power and water level.

Parameters
  • vtChannels (np.ndarray) – Numpy array with the channel POWER gains (power of the parallel AWGN channels).

  • dPt (float) – Total available power.

  • noiseVar (float) – Noise variance (power in linear scale).

  • Es (float) – Symbol energy (in linear scale).

Returns

(vtOptP, mu) – A tuple with vtOptP and mu, where vtOptP are the optimum powers, while mu is the water level.

Return type

(np.ndarray, float)

Module contents

Package with communication related modules such as modulators, channels, etc.

  1. summary

  2. extended summary

  3. routine listings

  4. see also

  5. notes

  6. references

  7. examples