Source code for hermespy.fec.repetition_encoder

# -*- coding: utf-8 -*-
"""
=================
Repetition Coding
=================

Repetition codes are among the most basic channel coding schemes.
The achieve redundancy by repeating all bits within a block during encoding.
"""

from __future__ import annotations

import numpy as np

from hermespy.core import Serializable
from .coding import Encoder

__author__ = "Tobias Kronauer"
__copyright__ = "Copyright 2023, Barkhausen Institut gGmbH"
__credits__ = ["Tobias Kronauer", "Jan Adler"]
__license__ = "AGPLv3"
__version__ = "1.2.0"
__maintainer__ = "Jan Adler"
__email__ = "jan.adler@barkhauseninstitut.org"
__status__ = "Prototype"


[docs] class RepetitionEncoder(Encoder, Serializable): """A channel coding scheme based on block-wise repetition of bits. During encoding, the repetition encoder repeats a block of :math:`K_n` :meth:`.bit_block_size` bits :math:`\\tilde{M}` :meth:`.repetitions` times, leading to a :meth:`.code_block_size` of .. math:: L_n = \\tilde{M} \\cdot K_n bits and a coding rate of .. math:: R_n = \\frac{K_n}{L_n} = \\frac{1}{\\tilde{M}} \\mathrm{.} Let .. math:: \\mathbf{x} = \\left[ x_1, x_2, \\dots, x_{K_n} \\right]^\\intercal \\in \\left\\lbrace 0, 1 \\right\\rbrace^{K_n} be the vector of input bits and .. math:: \\mathbf{y} = \\left[ y_1, y_2, \\dots, y_{K_n} \\right]^\\intercal \\in \\left\\lbrace 0, 1 \\right\\rbrace^{L_n} be the vector of repeated output bits. The implemented block repetition scheme can be described by .. math:: y_k = x_{k \\mod{K_n}} \\mathrm{,} assigning input bits to output bits by index. """ yaml_tag = "Repetition" __bit_block_size: int __repetitions: int def __init__(self, bit_block_size: int = 32, repetitions: int = 3) -> None: """ Args: bit_block_size (int, optional): The number of input bits per data block. repetitions (int, optional): The number of times the input bit block is repeated. Raises: ValueError: If `bit_block_size` times `repetitions` is smaller than `code_block_size`. """ # Default parameters Encoder.__init__(self) self.bit_block_size = bit_block_size self.repetitions = repetitions
[docs] def encode(self, bits: np.ndarray) -> np.ndarray: code = np.tile(bits, self.repetitions) return code
[docs] def decode(self, encoded_bits: np.ndarray) -> np.ndarray: if self.repetitions == 1: return encoded_bits code = encoded_bits.reshape((self.repetitions, self.bit_block_size)) # Majority voting bits = (np.sum(code, axis=0) / self.repetitions) >= 0.5 return bits.astype(int)
@property def bit_block_size(self) -> int: return self.__bit_block_size @bit_block_size.setter def bit_block_size(self, num_bits: int) -> None: if num_bits < 1: raise ValueError("Number data bits must be greater or equal to one") self.__bit_block_size = num_bits @property def code_block_size(self) -> int: return self.__repetitions * self.__bit_block_size @property def repetitions(self) -> int: """Number of times the bit block is repeated during encoding. Returns: int: Number of repetitions :math:`\\tilde{M}`. Raises: ValueError: If `repetitions` is smaller than one. ValueError: If `repetitions` is even. """ return self.__repetitions @repetitions.setter def repetitions(self, num: int) -> None: if num < 1: raise ValueError("The number of data bit repetitions must be at least one") if num % 2 == 0: raise ValueError("Repetitions must be an uneven integer") self.__repetitions = num