def polar_decode_llr(N, K, LLR0, use_f_exact=False): """ Decode a (N, K) polar code. P0 must be log likelihoods """ n = np.log2(N).astype(int) A = polar_hpw(N)[-K:] # We're not using all the elements in the P array, as each layer lamb # only uses 2**(n-lamb) elements. Given the current indexing it's still fine. P = np.empty((n + 1, N), dtype=float) B = np.zeros((n + 1, N), dtype=np.uint8) # Init P[0] = LLR0.copy() for phi in range(N): recursivlyCalcP_llr(n, phi, P, B, n) # print(f"Setting bit {phi}") if not phi in A: B[n, phi] = 0 else: if P[n, 0] > 0: B[n, phi] = 0 else: B[n, phi] = 1 if phi % 2 == 1: recursivelyUpdateB(n, phi, B, n) u_hat_full = B[n] return u_hat_full[A]
def polar_decode(N, K, P0): """ Decode a (N, K) polar code. P0 must be 1-normalized probabilities """ n = np.log2(N).astype(int) A = polar_hpw(N)[-K:] # We're not using all the elements in the P array, as each layer lamb # only uses 2**(n-lamb) elements. Given the current indexing it's still fine. P = np.empty((n + 1, N, 2), dtype=float) B = np.zeros((n + 1, N), dtype=np.uint8) for beta in range(N): P[0, beta, 0] = P0[beta] P[0, beta, 1] = 1 - P0[beta] for phi in range(N): recursivlyCalcP(n, phi, P, B, n) if not phi in A: B[n, phi] = 0 else: if P[n, 0, 0] > P[n, 0, 1]: B[n, phi] = 0 else: B[n, phi] = 1 if phi % 2 == 1: recursivelyUpdateB(n, phi, B, n) u_hat_full = B[n] return u_hat_full[A]
def select(B): A = polar_hpw(N)[-K:] # A is assumed placed in ROM u_hat = np.full(K, -1, np.int8) for i in range(K): u_hat[i] = B[A[i]] return u_hat
def polar_calc_R0_R1_set(N, K, *, ENABLE_R0=True, ENABLE_R1=True, ENABLE_REP=True, ENABLE_SPC=True): n = int(np.log2(N)) A_idx = polar_hpw(N)[-K:] A = np.zeros(N, np.uint) A[A_idx] = 1 rates = np.zeros((n + 1, N)) rates[0] = A.copy() # Start at the bottom level and propagate the rates for n_iter in range(n + 1): for i in range(int(2**(n - n_iter - 1))): rates[n_iter + 1, i] = 0.5 * (rates[n_iter, 2 * i] + rates[n_iter, 2 * i + 1]) # Then trim the tree down again alive = [(n, 0)] R1_nodes, R0_nodes, SPC_nodes, REP_nodes = ([], [], [], []) for n_iter in range(n - 1, -1, -1): new_alive = [] for node in alive: beta = node[1] parent_rate = rates[node[0], beta] node = (n_iter + 1, beta) if ENABLE_R1 and parent_rate == 1: R1_nodes.append(node) elif ENABLE_R0 and parent_rate == 0: R0_nodes.append(node) elif ENABLE_SPC and n_iter == 1 and parent_rate == 0.75: SPC_nodes.append(node) elif ENABLE_REP and n_iter == 1 and parent_rate == 0.25: REP_nodes.append(node) else: child0 = (n_iter, 2 * beta) child1 = (n_iter, 2 * beta + 1) new_alive.extend([child0, child1]) alive = new_alive return (set(R0_nodes), set(R1_nodes), set(REP_nodes), set(SPC_nodes))
def polar_decode_alternate(N, K, LLR, use_f_approx=False): # Sort the LLRs to match what this algorithm expects. # This sorting can be skipped if we simply don't reorder in the encoding phase LLR0 = LLR[polar_find_ordering(N)] # Sets are significantly faster when checking for contents, so converting is a major speedup A = polar_hpw(N)[-K:] A_set = set(A) all_bits = [] # This operation modifies the all_bits list with the correct bits polar_alt_recurse(LLR0, all_bits, A_set, use_f_approx=use_f_approx) all_bits_np = np.array(all_bits, np.uint8) return all_bits_np[A]
def polar_decode_ssc(N, K, LLR, soft_output=False): n = np.log2(N).astype(int) # Sort the LLRs to match what this algorithm expects. # This sorting can be skipped if we simply don't reorder in the encoding phase LLR0 = LLR[polar_find_ordering(N)] # Sets are significantly faster when checking for contents, so converting is a major speedup A = polar_hpw(N)[-K:] A_set = set(A) R0R1_set = polar_calc_R0_R1_set(N, K) all_bits = [] # This operation modifies the all_bits list with the correct bits polar_ssc_recurse(LLR0, (n, 0), all_bits, A_set, R0R1_set, soft_output) if soft_output: all_bits_np = np.array(all_bits) else: all_bits_np = np.array(all_bits, np.uint8) return all_bits_np[A]
'b': { 'style': 'filled', 'fillcolor': 'black', 'fontcolor': 'white', 'lblstyle': 'white' }, 'w': { 'style': 'filled', 'fillcolor': 'white', 'fontcolor': 'black', 'lblstyle': 'black' } } dot = Digraph() A_idx = polar_hpw(N)[-K:] A = np.zeros(N, np.uint) A[A_idx] = 1 n = int(np.log2(N)) # Calculate rates rates = np.zeros((n + 1, N)) rates[0] = A.copy() for i in range(N): if K > 0 and A[i] == 1: dot.attr('node', color_dict['b']) else: dot.attr('node', color_dict['w']) dot.node(f'$v_0^{i}$') for n_iter in range(n + 1):
def polar_encode(N, K, u, reorder=True): A = polar_hpw(N)[-K:] u_full = np.zeros(N, dtype=np.uint8) u_full[A] = u return polar_transform_pipelined(u_full, reorder)
def polar_encode_slow(N, K, u): G = polar_find_G(N) A = polar_hpw(N)[-K:] x = np.mod(u @ G[A], 2) return x