diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..4e1ef42 --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,31 @@ +# This workflows will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/.gitignore b/.gitignore index 7781feb..9f61ad3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,10 @@ .idea .python-version .pytest_cache -apak/* -firestore/*credentials* -src* +apak/ +src/ tests/_trial_temp* venv/ +*.egg-info/ +build/ +dist/ diff --git a/README.md b/README.md index dc823cc..27679b3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A package for Polar codes simulation. ## Installation ```bash -pip install git+git://github.com/fr0mhell/python-polar-coding.git#egg=python_polar_coding +pip install python-polar-coding ``` ## Example @@ -25,8 +25,8 @@ from python_polar_coding.simulation.functions import ( N = 128 K = 64 -design_snr = 2.0 -messages = 10000 +design_snr = 0.0 +messages = 1000 # SNR in [.0, .5, ..., 4.5, 5] snr_range = [i / 2 for i in range(11)] @@ -36,6 +36,11 @@ bpsk = SimpleBPSKModulationAWGN(fec_rate=K/N) result_ber = dict() result_fer = dict() +print('Python polar coding simulation') +print(f'Simulating ({codec.N}, {codec.K}) systematic polar code with Design SNR {codec.design_snr} dB') +print() +print('\tSNR (dB)|\tBER\t|\tFER') + for snr in snr_range: ber = 0 fer = 0 @@ -50,8 +55,10 @@ for snr in snr_range: ber += bit_errors fer += frame_error - result_ber[snr] = ber - result_fer[snr] = fer + result_ber[snr] = ber / (messages * codec.K) + result_fer[snr] = fer / messages + + print(f'\t{snr}\t|\t{result_ber[snr]:.4f}\t|\t{result_fer[snr]:.4f}') ``` ## Current progress @@ -73,10 +80,6 @@ for snr in snr_range: ## TODO -### General - -- [ ] Fix CRC-aided SC List decoder - ### Polar code construction - [ ] Arikan’s Monte-Carlo estimation [Section V.B](https://arxiv.org/pdf/1501.02473.pdf) @@ -86,6 +89,7 @@ for snr in snr_range: - [ ] [SC STACK Decoding](https://ieeexplore.ieee.org/document/6215306) - [ ] [Fast SSC List Decoding](https://arxiv.org/pdf/1703.08208.pdf) - [ ] [Generalized Fast SSC LIST Decoding](https://arxiv.org/pdf/1804.09508.pdf) +- [ ] CRC-aided decoders ### Modulation diff --git a/python-publish.yml b/python-publish.yml new file mode 100644 index 0000000..4e1ef42 --- /dev/null +++ b/python-publish.yml @@ -0,0 +1,31 @@ +# This workflows will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +name: Upload Python Package + +on: + release: + types: [created] + +jobs: + deploy: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel twine + - name: Build and publish + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + run: | + python setup.py sdist bdist_wheel + twine upload dist/* diff --git a/python_polar_coding/polar_codes/base/__init__.py b/python_polar_coding/polar_codes/base/__init__.py index f460230..06319db 100755 --- a/python_polar_coding/polar_codes/base/__init__.py +++ b/python_polar_coding/polar_codes/base/__init__.py @@ -1,4 +1,4 @@ -from .codec import BaseCRCPolarCodec, BasePolarCodec +from .codec import BasePolarCodec from .constants import * from .decoder import BaseDecoder, BaseTreeDecoder from .decoding_path import DecodingPathMixin diff --git a/python_polar_coding/polar_codes/base/codec.py b/python_polar_coding/polar_codes/base/codec.py index 2937650..fd2acf3 100644 --- a/python_polar_coding/polar_codes/base/codec.py +++ b/python_polar_coding/polar_codes/base/codec.py @@ -4,7 +4,7 @@ import numpy as np -from python_polar_coding.polar_codes import crc, pcc, utils +from python_polar_coding.polar_codes import pcc, utils from . import encoder @@ -132,61 +132,3 @@ def _construct_polar_mask(self, K): mask = sorted(mask, key=itemgetter(0)) # return mask, contains 0s or 1s due to frozen/info position return np.array([m[2] for m in mask]) - - -class BaseCRCPolarCodec(BasePolarCodec): - """Basic Polar code class with CRC support. - - Provides the support of CRC 16 and CRC 32. - - """ - encoder_class = encoder.EncoderWithCRC - - def __init__(self, N: int, K: int, - design_snr: float = 0.0, - is_systematic: bool = True, - crc_size: int = 32, - mask: Union[str, None] = None, - pcc_method: str = BasePolarCodec.BHATTACHARYYA): - - assert crc_size in [16, 32], f'Unsupported CRC size ({crc_size})' - assert K + crc_size < N, (f'Cannot create Polar code with N = {N},' - f' K = {K} and CRC {crc_size}.\n' - f'N must be bigger than (K + CRC size).') - self.crc_codec = crc.CRC(crc_size) - - super().__init__(N=N, K=K, - is_systematic=is_systematic, - design_snr=design_snr, - mask=mask, - pcc_method=pcc_method) - - def __str__(self): - return f'{super().__str__()}\nCRC {self.crc_size}' - - def to_dict(self): - d = super().to_dict() - d.update({'crc_size': self.crc_size}) - return d - - def init_encoder(self): - """Get Polar Encoder instance.""" - return self.encoder_class(mask=self.mask, n=self.n, - is_systematic=self.is_systematic, - crc_codec=self.crc_codec) - - @property - def crc_size(self): - return self.crc_codec.crc_size - - def _polar_code_construction(self, custom_mask=None) -> np.array: - """Construct polar mask. - - If a mask was given as a string of 1s and 0s, it converts it to array. - - """ - if custom_mask: - return np.array([int(b) for b in custom_mask]) - - info_length = self.K + self.crc_size - return self._construct_polar_mask(info_length) diff --git a/python_polar_coding/polar_codes/base/encoder.py b/python_polar_coding/polar_codes/base/encoder.py index 759a56a..7612d41 100644 --- a/python_polar_coding/polar_codes/base/encoder.py +++ b/python_polar_coding/polar_codes/base/encoder.py @@ -1,8 +1,6 @@ import numpy as np from numba import njit -from python_polar_coding.polar_codes.crc import CRC - class Encoder: """Polar Codes encoder.""" @@ -66,23 +64,3 @@ def _non_systematic_encode(message: np.array, n: int) -> np.array: message[p + start + step] = message[p + start + step] return message - - -class EncoderWithCRC(Encoder): - """Polar Encoder with CRC support.""" - - def __init__(self, - mask: np.array, - n: int, - crc_codec: CRC, - is_systematic: bool = True,): - super().__init__(mask, n, is_systematic) - self.crc_codec = crc_codec - - def encode(self, message: np.array): - """Compute CRC value and append to message before encoding.""" - message = np.append( - message, - self.crc_codec.compute_crc(message), - ) - return super().encode(message) diff --git a/python_polar_coding/polar_codes/base/parallel/__init__.py b/python_polar_coding/polar_codes/base/parallel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python_polar_coding/polar_codes/base/parallel/codec.py b/python_polar_coding/polar_codes/base/parallel/codec.py new file mode 100644 index 0000000..e69de29 diff --git a/python_polar_coding/polar_codes/base/parallel/decoder.py b/python_polar_coding/polar_codes/base/parallel/decoder.py new file mode 100644 index 0000000..e69de29 diff --git a/python_polar_coding/polar_codes/base/parallel/node.py b/python_polar_coding/polar_codes/base/parallel/node.py new file mode 100644 index 0000000..e69de29 diff --git a/python_polar_coding/polar_codes/sc_list_crc/__init__.py b/python_polar_coding/polar_codes/sc_list_crc/__init__.py deleted file mode 100644 index cd092a6..0000000 --- a/python_polar_coding/polar_codes/sc_list_crc/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .codec import SCListCRCPolarCodec -from .decoder import SCListCRCDecoder diff --git a/python_polar_coding/polar_codes/sc_list_crc/codec.py b/python_polar_coding/polar_codes/sc_list_crc/codec.py deleted file mode 100644 index df4d514..0000000 --- a/python_polar_coding/polar_codes/sc_list_crc/codec.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Union - -from ..base.codec import BaseCRCPolarCodec -from .decoder import SCListCRCDecoder - - -class SCListCRCPolarCodec(BaseCRCPolarCodec): - """Polar code with SC List decoding algorithm and CRC.""" - decoder_class = SCListCRCDecoder - - def __init__(self, N: int, K: int, - crc_size: int = 32, - design_snr: float = 0.0, - is_systematic: bool = True, - mask: Union[str, None] = None, - pcc_method: str = BaseCRCPolarCodec.BHATTACHARYYA, - L: int = 1): - - self.L = L - super().__init__(N=N, K=K, - is_systematic=is_systematic, - design_snr=design_snr, - mask=mask, - pcc_method=pcc_method, - crc_size=crc_size) - - def init_decoder(self): - return self.decoder_class(n=self.n, mask=self.mask, - is_systematic=self.is_systematic, - L=self.L, crc_codec=self.crc_codec) - - def to_dict(self): - d = super().to_dict() - d.update({'L': self.L}) - return d diff --git a/python_polar_coding/polar_codes/sc_list_crc/decoder.py b/python_polar_coding/polar_codes/sc_list_crc/decoder.py deleted file mode 100644 index b75b3c4..0000000 --- a/python_polar_coding/polar_codes/sc_list_crc/decoder.py +++ /dev/null @@ -1,26 +0,0 @@ -import numpy as np - -from python_polar_coding.polar_codes.crc import CRC - -from ..sc_list import SCListDecoder - - -class SCListCRCDecoder(SCListDecoder): - """SC List decoding with CRC.""" - - def __init__(self, - n: int, - mask: np.array, - crc_codec: CRC, - is_systematic: bool = True, - L: int = 1): - super().__init__(n=n, mask=mask, is_systematic=is_systematic, L=L) - self.crc_codec = crc_codec - - @property - def best_result(self): - """Result from the best path.""" - for result in self.result: - if self.crc_codec.check_crc(result): - return result[:-self.crc_codec.crc_size] - return super().best_result diff --git a/setup.py b/setup.py index 960e674..d0a59b6 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setuptools.setup( name='python-polar-coding', - version='0.1.0', + version='0.0.1', description='Polar coding implementation in Python', @@ -37,7 +37,7 @@ 'Programming Language :: Python :: 3 :: Only', ], - keywords='polar codes, fec', + keywords='polar codes, fec, simulation', packages=setuptools.find_packages(),