Finished cpp proximal decoder implementation

This commit is contained in:
Andreas Tsouchlos 2022-11-25 14:00:19 +01:00
parent 9818193386
commit 066d9d85d2
3 changed files with 33 additions and 48 deletions

2
.gitignore vendored
View File

@ -2,6 +2,8 @@ latex/build/
latex/tmp/
sw/cpp_modules
sw/cpp/build
sw/cpp/cmake-build-debug
sw/cpp/cmake-build-release
sw/sim_saves/
.idea
__pycache__

View File

@ -1,14 +1,31 @@
cmake_minimum_required (VERSION 3.0)
project(cpp_decoders)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to 'Release' as none was specified.")
set(CMAKE_BUILD_TYPE
Release
CACHE STRING "Choose the type of build." FORCE)
set_property(
CACHE CMAKE_BUILD_TYPE
PROPERTY STRINGS
"Debug"
"Release")
endif()
set(CMAKE_CXX_STANDARD 23)
find_package(Eigen3 3.3 REQUIRED NO_MODULE)
find_package(pybind11 CONFIG REQUIRED)
include_directories(${pybind11_INCLUDE_DIRS})
find_package(OpenMP REQUIRED)
pybind11_add_module(cpp_decoders src/cpp_decoders.cpp)
target_link_libraries(cpp_decoders PRIVATE Eigen3::Eigen)
target_link_libraries(cpp_decoders PRIVATE Eigen3::Eigen OpenMP::OpenMP_CXX)
set(INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../cpp_modules)

View File

@ -1,53 +1,14 @@
#include <Eigen/Cholesky>
#include <Eigen/Dense>
#include <iostream>
#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/eigen.h>
#include <bit>
/*
import numpy as np
class ProximalDecoder:
"""Class implementing the Proximal Decoding algorithm. See "Proximal
Decoding for LDPC Codes"
by Tadashi Wadayama, and Satoshi Takabe.
"""
def decode(self, y: np.array) -> np.array:
"""Decode a received signal. The algorithm is detailed in 3.2, p.3.
This function assumes a BPSK modulated signal and an AWGN channel.
:param y: Vector of received values. (y = x + w, where 'x' is
element of [-1, 1]^n and 'w' is noise)
:return: Most probably sent codeword (element of [0, 1]^n). If
decoding fails, the returned value is 'None'
"""
s = np.zeros(self._n)
x_hat = np.zeros(self._n)
for k in range(self._K):
r = s - self._step_size * self._L_awgn(s, y)
s = r - self._gamma * self._grad_h(r)
s = self._projection(s) # Equation (15)
x_hat = np.sign(s)
# Map the codeword from [ -1, 1]^n to [0, 1]^n
x_hat = (x_hat == -1) * 1
if self._check_parity(x_hat):
return x_hat
return None
* */
namespace py11 = pybind11;
using namespace pybind11::literals;
@ -66,6 +27,8 @@ public:
double gamma, double eta)
: mN(H.cols()), mK(K), mOmega(omega), mGamma(gamma), mEta(eta), mH(H),
mH_zero_indices(find_zero(H)) {
Eigen::setNbThreads(8);
}
const std::optional<Eigen::RowVectorXi>
@ -76,10 +39,14 @@ public:
for (std::size_t i = 0; i < mK; ++i) {
r = s - mOmega * L_awgn(s, y);
s = projection(r - mGamma * grad_H(r));
x_hat = s.cast<int>().cwiseSign();
x_hat = (x_hat.array() - 1).matrix() / (-2);
x_hat = s.unaryExpr([](double d) {
uint64_t bits = std::bit_cast<uint64_t>(d);
// Return the sign bit: 1 for negative, 0 for positive
return (bits >> 63);
}).cast<int>();
if (check_parity(x_hat)) {
return x_hat;
@ -96,8 +63,7 @@ private:
const double mGamma;
const double mEta;
const MatrixXiR mH;
const MatrixXiR mH;
const std::vector<Eigen::Index> mH_zero_indices;