Skip to content

komm.CrossQAMConstellation

Cross quadrature amplitude modulation (cross-QAM) constellation. It is a complex one-dimensional constellation defined only for orders $M = 2^k$ with $k$ odd and $k \geq 5$ (that is, $M = 32, 128, 512, \ldots$), for which a square QAM constellation does not exist. More precisely, start with a smaller square QAM constellation with order $2^{k-1}$ and extend each side of the QAM square by adding $2^{k-3}$ points, ignoring the corners in this extension; this leaves a total of $2^{k-1} + 4 \cdot 2^{k-3} = 2^k$ points resulting in a cross shape. Equivalently, it may be obtained from a bigger $L \times L$ square QAM constellation, where $L = 3 \sqrt{2^{k-3}}$, by removing the four corner regions. For more details, see Hay04, Sec. 6.4.

Parameters:

  • order (int)

    The order $M$ of the constellation. Must be of the form $M = 2^k$ with $k$ odd and $k \geq 5$.

  • delta (float)

    The distance $\delta$ between adjacent symbols (along the in-phase and quadrature axes). The default value is 2.0.

  • phase_offset (float)

    The phase offset $\phi$ of the constellation (in turns, not radians). The default value is 0.0.

Examples:

The $32$-cross-QAM constellation with $\delta = 2$ is depicted below.

32-cross-QAM constellation.

>>> const = komm.CrossQAMConstellation(32)

matrix Array2D[complexfloating] cached property

The constellation matrix $\mathbf{X}$.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.matrix
array([[-5.-3.j],
       [-5.-1.j],
       [-5.+1.j],
       [-5.+3.j],
       [-3.-5.j],
       [-3.-3.j],
       [-3.-1.j],
       [-3.+1.j],
       [-3.+3.j],
       [-3.+5.j],
       [-1.-5.j],
       [-1.-3.j],
       [-1.-1.j],
       [-1.+1.j],
       [-1.+3.j],
       [-1.+5.j],
       [ 1.-5.j],
       [ 1.-3.j],
       [ 1.-1.j],
       [ 1.+1.j],
       [ 1.+3.j],
       [ 1.+5.j],
       [ 3.-5.j],
       [ 3.-3.j],
       [ 3.-1.j],
       [ 3.+1.j],
       [ 3.+3.j],
       [ 3.+5.j],
       [ 5.-3.j],
       [ 5.-1.j],
       [ 5.+1.j],
       [ 5.+3.j]])

order int property

The order $M$ of the constellation.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.order
32

dimension int property

The dimension $N$ of the constellation.

For the cross-QAM constellation, it is given by $N = 1$.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.dimension
1

mean()

Computes the mean $\mathbf{m}$ of the constellation given prior probabilities $p_i$ of the constellation symbols. It is given by $$ \mathbf{m} = \sum_{i \in [0:M)} p_i \mathbf{x}_i. $$

Parameters:

  • priors (ArrayLike | None)

    The prior probabilities of the constellation symbols. Must be a 1D-array whose size is equal to the order $M$ of the constellation. If not given, uniform priors are assumed.

Returns:

  • mean (Array1D[complexfloating])

    The mean $\mathbf{m}$ of the constellation.

For uniform priors, the mean of the cross-QAM constellation is given by $$ \mathbf{m} = 0. $$

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.mean()
array([0.+0.j])

mean_energy()

Computes the mean energy $E$ of the constellation given prior probabilities $p_i$ of the constellation symbols. It is given by $$ E = \sum_{i \in [0:M)} p_i \lVert \mathbf{x}_i \rVert^2. $$

Parameters:

  • priors (ArrayLike | None)

    The prior probabilities of the constellation symbols. Must be a 1D-array whose size is equal to the order $M$ of the constellation. If not given, uniform priors are assumed.

Returns:

  • mean_energy (floating)

    The mean energy $E$ of the constellation.

For uniform priors, the mean energy of the cross-QAM constellation is given by $$ E = \frac{\delta^2}{192} (31 M - 32). $$

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.mean_energy()
np.float64(20.0)

minimum_distance()

Computes the minimum Euclidean distance $d_\mathrm{min}$ of the constellation. It is given by $$ d_\mathrm{min} = \min_ { i, j \in [0:M), ~ i \neq j } \lVert \mathbf{x}_i - \mathbf{x}_j \rVert. $$

For the cross-QAM constellation, the minimum distance is given by $$ d_{\min} = \delta. $$

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.minimum_distance()
np.float64(2.0)

indices_to_symbols()

Returns the constellation symbols corresponding to the given indices.

Parameters:

  • indices (ArrayLike)

    The indices to be converted to symbols. Must be an array of integers in $[0:M)$.

Returns:

  • symbols (NDArray[complexfloating])

    The symbols corresponding to the given indices. Has the same shape as indices, but with the last dimension expanded by a factor of $N$.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.indices_to_symbols([12, 0])
array([-1.-1.j, -5.-3.j])

closest_indices()

Returns the indices of the constellation symbols closest to the given received points.

Parameters:

  • received (ArrayLike)

    The received points. Must be an array whose last dimension is a multiple of $N$.

Returns:

  • indices (NDArray[integer])

    The indices of the symbols closest to the received points. Has the same shape as received, but with the last dimension contracted by a factor of $N$.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.closest_indices([-1.1 - 0.9j, 5.2 + 5.1j])
array([12, 31])

closest_symbols()

Returns the constellation symbols closest to the given received points.

Parameters:

  • received (ArrayLike)

    The received points. Must be an array whose last dimension is a multiple of $N$.

Returns:

  • symbols (NDArray[complexfloating])

    The symbols closest to the received points. Has the same shape as received.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.closest_symbols([-1.1 - 0.9j, 5.2 + 5.1j])
array([-1.-1.j,  5.+3.j])

posteriors()

Returns the posterior probabilities of each constellation symbol given received points, the noise power, and prior probabilities.

The posteriors are computed under the Gaussian channel model $Y = X + Z$, assuming that each received point is the transmitted symbol corrupted by additive Gaussian noise of power $\sigma_Z^2$. For real-valued constellations the noise is real Gaussian with variance $\sigma_Z^2$; for complex-valued constellations it is circularly symmetric complex Gaussian, with the noise power equally divided between the real and imaginary parts, i.e., $\mathrm{E}[\mathrm{Re}\{Z_n\}^2] = \mathrm{E}[\mathrm{Im}\{Z_n\}^2] = \sigma_Z^2/2$.

Parameters:

  • received (ArrayLike)

    The received points. Must be an array whose last dimension is a multiple of $N$.

  • noise_power (float)

    The noise power (variance) $\sigma_Z^2$.

  • priors (ArrayLike | None)

    The prior probabilities of the symbols. Must be a 1D-array whose size is equal to $M$. If not given, uniform priors are assumed.

Returns:

  • posteriors (NDArray[floating])

    The posterior probabilities of each symbol given the received points. Has the same shape as received, but with the last dimension changed by a factor of $M / N$.

Examples:

>>> const = komm.CrossQAMConstellation(32)
>>> const.posteriors([-1.1 - 0.9j], noise_power=2.0).round(3)
array([0.   , 0.   , 0.   , 0.   , 0.   , 0.011, 0.101, 0.017, 0.   ,
       0.   , 0.   , 0.068, 0.613, 0.101, 0.   , 0.   , 0.   , 0.008,
       0.068, 0.011, 0.   , 0.   , 0.   , 0.   , 0.   , 0.   , 0.   ,
       0.   , 0.   , 0.   , 0.   , 0.   ])