def BER(yi,yd,Ni,Nd,ibits,dbits): xi=np.zeros((yi.size,Ni)) xd=np.zeros((yd.size,Nd)) for i in range(0,yi.size): xi[i]=dec2bitarray(int(yi[i]),Ni) beri=np.sum(np.not_equal(xi.reshape((1,-1)),np.matrix(ibits).H.reshape((1,-1))))/xi.size for i in range(0,yd.size): xd[i]=dec2bitarray(int(yd[i]),Nd) berd=np.sum(np.not_equal(xd.reshape((1,-1)),np.matrix(dbits).H.reshape((1,-1))))/xd.size return beri, berd
def cyclic_code_genpoly(n, k): """ Generate all possible generator polynomials for a (n, k)-cyclic code. Parameters ---------- n : int Code blocklength of the cyclic code. k : int Information blocklength of the cyclic code. Returns ------- poly_list : 1D ndarray of ints A list of generator polynomials (represented as integers) for the (n, k)-cyclic code. """ if n % 2 == 0: raise ValueError("n cannot be an even number") for m in arange(1, 18): if (2**m - 1) % n == 0: break x_gf = GF(arange(1, 2**m), m) coset_fields = x_gf.cosets() coset_leaders = array([]) minpol_degrees = array([]) for field in coset_fields: coset_leaders = concatenate( (coset_leaders, array([field.elements[0]]))) minpol_degrees = concatenate( (minpol_degrees, array([len(field.elements)]))) y_gf = GF(coset_leaders, m) minpol_list = y_gf.minpolys() idx_list = arange(1, len(minpol_list)) poly_list = array([]) for i in range(1, 2**len(minpol_list)): i_array = dec2bitarray(i, len(minpol_list)) subset_array = minpol_degrees[i_array == 1] if int(subset_array.sum()) == (n - k): poly_set = minpol_list[i_array == 1] gpoly = 1 for poly in poly_set: gpoly_array = dec2bitarray(gpoly, 2**m) poly_array = dec2bitarray(poly, 2**m) gpoly = bitarray2dec(convolve(gpoly_array, poly_array) % 2) poly_list = concatenate((poly_list, array([gpoly]))) return poly_list.astype(int)
def _backward_recursion(trellis, msg_length, noise_variance, sys_symbols, non_sys_symbols, branch_probs, priors, b_state_metrics): n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs codeword_array = empty(n, 'int') next_state_table = trellis.next_state_table output_table = trellis.output_table # Backward recursion for reverse_time_index in reversed(range(1, msg_length + 1)): for current_state in range(number_states): for current_input in range(number_inputs): next_state = next_state_table[current_state, current_input] code_symbol = output_table[current_state, current_input] codeword_array = dec2bitarray(code_symbol, n) parity_bit = codeword_array[1] msg_bit = codeword_array[0] rx_symbol_0 = sys_symbols[reverse_time_index - 1] rx_symbol_1 = non_sys_symbols[reverse_time_index - 1] branch_prob = _compute_branch_prob(msg_bit, parity_bit, rx_symbol_0, rx_symbol_1, noise_variance) branch_probs[current_input, current_state, reverse_time_index - 1] = branch_prob b_state_metrics[current_state, reverse_time_index-1] += \ (b_state_metrics[next_state, reverse_time_index] * branch_prob * priors[current_input, reverse_time_index-1]) b_state_metrics[:,reverse_time_index-1] /= \ b_state_metrics[:,reverse_time_index-1].sum()
def _backward_recursion(trellis, msg_length, noise_variance, sys_symbols, non_sys_symbols, branch_probs, priors, b_state_metrics): n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs codeword_array = empty(n, 'int') next_state_table = trellis.next_state_table output_table = trellis.output_table # Backward recursion for reverse_time_index in reversed(range(1, msg_length+1)): for current_state in range(number_states): for current_input in range(number_inputs): next_state = next_state_table[current_state, current_input] code_symbol = output_table[current_state, current_input] codeword_array = dec2bitarray(code_symbol, n) parity_bit = codeword_array[1] msg_bit = codeword_array[0] rx_symbol_0 = sys_symbols[reverse_time_index-1] rx_symbol_1 = non_sys_symbols[reverse_time_index-1] branch_prob = _compute_branch_prob(msg_bit, parity_bit, rx_symbol_0, rx_symbol_1, noise_variance) branch_probs[current_input, current_state, reverse_time_index-1] = branch_prob b_state_metrics[current_state, reverse_time_index-1] += \ (b_state_metrics[next_state, reverse_time_index] * branch_prob * priors[current_input, reverse_time_index-1]) b_state_metrics[:,reverse_time_index-1] /= \ b_state_metrics[:,reverse_time_index-1].sum()
def BER(y, bits, N): x = np.zeros((y.size, N)) for i in range(0, y.size): x[i] = dec2bitarray(int(y[i]), N) return np.sum( np.not_equal(x.reshape((1, x.size)), np.matrix(bits).H.reshape((1, bits.size)))) / x.size
def get_const_symbols(mode='QAM', m=16): ''' Implement either QAM or PSK ''' # m is given nbps = np.log2(m) # simplify constellations to 2^k alphabets if nbps.is_integer(): nbps = nbps.astype(int) else: raise Exception('QAM: m must be a power of 2') # switch between modes if mode == 'QAM': blist = [util.dec2bitarray(x,nbps) for x in range(m)] bits = np.concatenate(blist) mod = comm.modulation.QAMModem(m) syms = mod.modulate(bits) / np.sqrt(10) return syms elif mode == 'PSK': thetas = [x/m * 2 * np.pi for x in range(m)] syms = np.exp(1j*np.asarray(thetas)) return syms else: raise Exception('Invalid initialization!')
def demodulate(self, input_symbols, demod_type, noise_var=0): """ Demodulate (map) a set of constellation symbols to corresponding bits. Supports hard-decision demodulation only. Parameters ---------- input_symbols : 1D ndarray of complex floats Input symbols to be demodulated. demod_type : string 'hard' for hard decision output (bits) 'soft' for soft decision output (LLRs) noise_var : float AWGN variance. Needs to be specified only if demod_type is 'soft' Returns ------- demod_bits : 1D ndarray of ints Corresponding demodulated bits. """ if demod_type == 'hard': index_list = list(map(lambda i: argmin(abs(input_symbols[i] - self.constellation)), \ range(0, len(input_symbols)))) demod_bits = hstack( list( map(lambda i: dec2bitarray(i, self.num_bits_symbol), index_list))) elif demod_type == 'soft': demod_bits = zeros(len(input_symbols) * self.num_bits_symbol) for i in arange(len(input_symbols)): current_symbol = input_symbols[i] for bit_index in arange(self.num_bits_symbol): llr_num = 0 llr_den = 0 for const_index in self.symbol_mapping: if (const_index >> bit_index) & 1: llr_num = llr_num + exp( (-abs(current_symbol - self.constellation[const_index])**2) / noise_var) else: llr_den = llr_den + exp( (-abs(current_symbol - self.constellation[const_index])**2) / noise_var) demod_bits[i * self.num_bits_symbol + self.num_bits_symbol - 1 - bit_index] = log( llr_num / llr_den) else: pass # throw an error return demod_bits
def _test_qam_mapper_demapper(self, m): mapper = util.QamMapper(m) data_in = np.hstack( [dec2bitarray(n, int(np.sqrt(m))) for n in range(m)]) qam_data = mapper.modulate(data_in) self.assertEqual(len(qam_data), (len(data_in) // np.log2(m))) self.assertTrue(len(set(qam_data)) == m) data_out = mapper.demodulate(qam_data) np.testing.assert_array_almost_equal(data_out, data_in)
def ts_i(L, Ni, index_SA): # index=np.array([1,1,1,0,0,1,1,1]) index = [index_SA] # index=np.array([0,0,1,1,2,2,3,3]) index = np.repeat(index, L // len(index)) ibits = np.zeros((Ni, index.size)) for i in range(0, index.size): ibits[:, i] = dec2bitarray(int(index[i]), Ni) # plt.figure() # plt.plot(index) # ibits=np.random.choice([0,1],L//k*Ni).reshape((Ni,-1)).repeat(k,1) return ibits
def demodulate(self, input_symbols, demod_type, noise_var=0): """ Demodulate (map) a set of constellation symbols to corresponding bits. Parameters ---------- input_symbols : 1D ndarray of complex floats Input symbols to be demodulated. demod_type : string 'hard' for hard decision output (bits) 'soft' for soft decision output (LLRs) noise_var : float AWGN variance. Needs to be specified only if demod_type is 'soft' Returns ------- demod_bits : 1D ndarray of ints Corresponding demodulated bits. """ if demod_type == 'hard': index_list = abs(input_symbols - self._constellation[:, None]).argmin(0) demod_bits = dec2bitarray(index_list, self.num_bits_symbol) elif demod_type == 'soft': demod_bits = zeros(len(input_symbols) * self.num_bits_symbol) for i in arange(len(input_symbols)): current_symbol = input_symbols[i] for bit_index in arange(self.num_bits_symbol): llr_num = 0 llr_den = 0 for const_index in self.symbol_mapping: if (const_index >> bit_index) & 1: llr_num = llr_num + exp( (-abs(current_symbol - self._constellation[const_index])**2) / noise_var) else: llr_den = llr_den + exp( (-abs(current_symbol - self._constellation[const_index])**2) / noise_var) demod_bits[i * self.num_bits_symbol + self.num_bits_symbol - 1 - bit_index] = log( llr_num / llr_den) else: raise ValueError('demod_type must be "hard" or "soft"') return demod_bits
def cyclic_code_genpoly(n, k): if n % 2 == 0: raise ValueError, "n cannot be an even number" for m in arange(1, 18): if (2**m - 1) % n == 0: break x_gf = GF(arange(1, 2**m), m) coset_fields = x_gf.cosets() coset_leaders = array([]) minpol_degrees = array([]) for field in coset_fields: coset_leaders = concatenate( (coset_leaders, array([field.elements[0]]))) minpol_degrees = concatenate( (minpol_degrees, array([len(field.elements)]))) y_gf = GF(coset_leaders, m) minpol_list = y_gf.minpolys() idx_list = arange(1, len(minpol_list)) poly_list = array([]) for i in xrange(1, 2**len(minpol_list)): i_array = dec2bitarray(i, len(minpol_list)) subset_array = minpol_degrees[i_array == 1] if int(subset_array.sum()) == (n - k): poly_set = minpol_list[i_array == 1] gpoly = 1 for poly in poly_set: gpoly_array = dec2bitarray(gpoly, 2**m) poly_array = dec2bitarray(poly, 2**m) gpoly = bitarray2dec(convolve(gpoly_array, poly_array) % 2) poly_list = concatenate((poly_list, array([gpoly]))) return poly_list.astype(int)
def cyclic_code_genpoly(n, k): if n%2 == 0: raise ValueError, "n cannot be an even number" for m in arange(1, 18): if (2**m-1)%n == 0: break x_gf = GF(arange(1, 2**m), m) coset_fields = x_gf.cosets() coset_leaders = array([]) minpol_degrees = array([]) for field in coset_fields: coset_leaders = concatenate((coset_leaders, array([field.elements[0]]))) minpol_degrees = concatenate((minpol_degrees, array([len(field.elements)]))) y_gf = GF(coset_leaders, m) minpol_list = y_gf.minpolys() idx_list = arange(1, len(minpol_list)) poly_list = array([]) for i in xrange(1, 2**len(minpol_list)): i_array = dec2bitarray(i, len(minpol_list)) subset_array = minpol_degrees[i_array == 1] if int(subset_array.sum()) == (n-k): poly_set = minpol_list[i_array == 1] gpoly = 1 for poly in poly_set: gpoly_array = dec2bitarray(gpoly, 2**m) poly_array = dec2bitarray(poly, 2**m) gpoly = bitarray2dec(convolve(gpoly_array, poly_array) % 2) poly_list = concatenate((poly_list, array([gpoly]))) return poly_list.astype(int)
def training_symbols(N, Nd, Ni): #Ni=2 #Nd=2 #N=16 index = np.arange(0, 2**Ni) ibits = np.zeros([Ni, 2**Ni]) for i in range(0, 2**Ni): ibits[:, i] = dec2bitarray(index[i], Ni) #!!!!auf ML_approx_unknown Zeile 93 anpassen!! ibits_ = ibits for j in range(1, N // (2**Ni)): ibits = np.concatenate((ibits_, ibits), 1) j = j + 1 #ibits=np.transpose(ibits_).reshape([-1,1]) dbits = np.random.choice([0, 1], N * Nd).reshape((Nd, -1)) #dbits=np.random.choice([1],N*Nd).reshape((Nd,-1)) return ibits, dbits
def demodulate(self, input_symbols, demod_type, noise_var = 0): """ Demodulate (map) a set of constellation symbols to corresponding bits. Supports hard-decision demodulation only. Parameters ---------- input_symbols : 1D ndarray of complex floats Input symbols to be demodulated. demod_type : string 'hard' for hard decision output (bits) 'soft' for soft decision output (LLRs) noise_var : float AWGN variance. Needs to be specified only if demod_type is 'soft' Returns ------- demod_bits : 1D ndarray of ints Corresponding demodulated bits. """ if demod_type == 'hard': index_list = map(lambda i: argmin(abs(input_symbols[i] - self.constellation)), \ range(0, len(input_symbols))) demod_bits = hstack(map(lambda i: dec2bitarray(i, self.num_bits_symbol), index_list)) elif demod_type == 'soft': demod_bits = zeros(len(input_symbols) * self.num_bits_symbol) for i in arange(len(input_symbols)): current_symbol = input_symbols[i] for bit_index in arange(self.num_bits_symbol): llr_num = 0 llr_den = 0 for const_index in self.symbol_mapping: if (const_index >> bit_index) & 1: llr_num = llr_num + exp((-abs(current_symbol - self.constellation[const_index])**2)/noise_var) else: llr_den = llr_den + exp((-abs(current_symbol - self.constellation[const_index])**2)/noise_var) demod_bits[i*self.num_bits_symbol + self.num_bits_symbol - 1 - bit_index] = log(llr_num/llr_den) else: pass # throw an error return demod_bits
def demodulate(self, data): """ Demodulate (map) a set of constellation symbols to corresponding bits. Supports hard-decision demodulation only. Parameters ---------- data : 1D ndarray of complex floats Input symbols to be demodulated. Returns ------- demod_bits : 1D ndarray of ints Corresponding demodulated bits. """ index_list = map(lambda i: np.argmin(abs(data[i] - self.constellation)), range(0, len(data))) demod_bits = np.hstack(list(map(lambda i: dec2bitarray(i, self.num_bits_symbol), index_list))) return demod_bits
def demodulate(self, input_symbols): """ Demodulate (map) a set of constellation symbols to corresponding bits. Supports hard-decision demodulation only. Parameters ---------- input_symbols : 1D ndarray of complex floats Input symbols to be demodulated. Returns ------- demod_bits : 1D ndarray of ints Corresponding demodulated bits. """ num_bits_symbol = int(log2(self.m)) index_list = map(lambda i: argmin(abs(input_symbols[i] - self.constellation)), \ xrange(0, len(input_symbols))) demod_bits = hstack(map(lambda i: dec2bitarray(i, num_bits_symbol), index_list)) return demod_bits
def BER(y, bits, N): x = np.zeros((y.size, N)) for i in range(0, y.size): x[i] = dec2bitarray(int(y[i]), N) return np.sum( np.not_equal(x.reshape((1, x.size)), np.matrix(bits).H.reshape((1, bits.size)))) / x.size #r_BB=r.channel(H,sender_.ibits,s_BB_off,SNR_noise_dB,SNR_RA_dB,filter_) # ##r_BB=f.ML_FLL(r_BB,g) # #r_BBr_MF=r.Matched_Filter(r_BB.real,filter_.ir() ,filter_.n_up) #r_BBi_MF=r.Matched_Filter(r_BB.imag,filter_.ir() ,filter_.n_up) #r_=r_BBr_MF+1j*r_BBi_MF # ##r_=s.channel(H,ibits,symbols,RA,SNR_noise_dB,SNR_RA_dB) # #yi,yd=r.detector(SNR_RA_dB,H,bpsk_map,r_) #beri=r.BER(yi,sender_.ibits,Ni) #berd=r.BER(yd,sender_.dbits,Nd) #print(beri,berd) ##return beri,berd
def conv_encode(message_bits, trellis, code_type = 'default', puncture_matrix=None): """ Encode bits using a convolutional code. Parameters ---------- message_bits : 1D ndarray containing {0, 1} Stream of bits to be convolutionally encoded. generator_matrix : 2-D ndarray of ints Generator matrix G(D) of the convolutional code using which the input bits are to be encoded. M : 1D ndarray of ints Number of memory elements per input of the convolutional encoder. Returns ------- coded_bits : 1D ndarray containing {0, 1} Encoded bit stream. """ k = trellis.k n = trellis.n total_memory = trellis.total_memory rate = float(k)/n if puncture_matrix is None: puncture_matrix = np.ones((trellis.k, trellis.n)) number_message_bits = np.size(message_bits) # Initialize an array to contain the message bits plus the truncation zeros if code_type == 'default': inbits = np.zeros(number_message_bits + total_memory + total_memory % k, 'int') number_inbits = number_message_bits + total_memory + total_memory % k # Pad the input bits with M zeros (L-th terminated truncation) inbits[0:number_message_bits] = message_bits number_outbits = int(number_inbits/rate) else: inbits = message_bits number_inbits = number_message_bits number_outbits = int((number_inbits + total_memory)/rate) outbits = np.zeros(number_outbits, 'int') p_outbits = np.zeros(int(number_outbits* puncture_matrix[0:].sum()/np.size(puncture_matrix, 1)), 'int') next_state_table = trellis.next_state_table output_table = trellis.output_table # Encoding process - Each iteration of the loop represents one clock cycle current_state = 0 j = 0 for i in range(int(number_inbits/k)): # Loop through all input bits current_input = bitarray2dec(inbits[i*k:(i+1)*k]) current_output = output_table[current_state][current_input] outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 if code_type == 'rsc': term_bits = dec2bitarray(current_state, trellis.total_memory) term_bits = term_bits[::-1] for i in range(trellis.total_memory): current_input = bitarray2dec(term_bits[i*k:(i+1)*k]) current_output = output_table[current_state][current_input] outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 j = 0 for i in range(number_outbits): if puncture_matrix[0][i % np.size(puncture_matrix, 1)] == 1: p_outbits[j] = outbits[i] j = j + 1 return p_outbits
import numpy as np from random import randint from commpy.modulation import QAMModem from commpy.filters import rrcosfilter from commpy.utilities import bitarray2dec, dec2bitarray np.set_printoptions(threshold=np.nan) N = 1024 # output size M = 16 mod1 = QAMModem(M) # QAM16 sB = dec2bitarray(randint(0, 2**(mod1.num_bits_symbol * N * M / 4)), (mod1.num_bits_symbol * N * M / 4)) # Random bit stream # print np.array2string(sB) sQ = mod1.modulate(sB) # Modulated baud points print np.array2string(np.abs(sQ)) sPSF = rrcosfilter(N * 4, 0.2, 1, 4000)[1] qW = np.convolve(sPSF, sQ) # Waveform with PSF #print np.array2string(qW)
def __init__(self, memory, g_matrix, feedback = 0, code_type = 'default'): [self.k, self.n] = g_matrix.shape if code_type == 'rsc': for i in range(self.k): g_matrix[i][i] = feedback self.total_memory = memory.sum() self.number_states = pow(2, self.total_memory) self.number_inputs = pow(2, self.k) self.next_state_table = np.zeros([self.number_states, self.number_inputs], 'int') self.output_table = np.zeros([self.number_states, self.number_inputs], 'int') # Compute the entries in the next state table and the output table for current_state in range(self.number_states): for current_input in range(self.number_inputs): outbits = np.zeros(self.n, 'int') # Compute the values in the output_table for r in range(self.n): output_generator_array = np.zeros(self.k, 'int') shift_register = dec2bitarray(current_state, self.total_memory) for l in range(self.k): # Convert the number representing a polynomial into a # bit array generator_array = dec2bitarray(g_matrix[l][r], memory[l]+1) # Loop over M delay elements of the shift register # to compute their contribution to the r-th output for i in range(memory[l]): outbits[r] = (outbits[r] + \ (shift_register[i+l]*generator_array[i+1])) % 2 output_generator_array[l] = generator_array[0] if l == 0: feedback_array = (dec2bitarray(feedback, memory[l]) * shift_register[0:memory[l]]).sum() shift_register[1:memory[l]] = \ shift_register[0:memory[l]-1] shift_register[0] = (dec2bitarray(current_input, self.k)[0] + feedback_array) % 2 else: feedback_array = (dec2bitarray(feedback, memory[l]) * shift_register[l+memory[l-1]-1:l+memory[l-1]+memory[l]-1]).sum() shift_register[l+memory[l-1]:l+memory[l-1]+memory[l]-1] = \ shift_register[l+memory[l-1]-1:l+memory[l-1]+memory[l]-2] shift_register[l+memory[l-1]-1] = \ (dec2bitarray(current_input, self.k)[l] + feedback_array) % 2 # Compute the contribution of the current_input to output outbits[r] = (outbits[r] + \ (np.sum(dec2bitarray(current_input, self.k) * \ output_generator_array + feedback_array) % 2)) % 2 # Update the ouput_table using the computed output value self.output_table[current_state][current_input] = \ bitarray2dec(outbits) # Update the next_state_table using the new state of # the shift register self.next_state_table[current_state][current_input] = \ bitarray2dec(shift_register)
def conv_encode(message_bits, trellis, termination = 'term', puncture_matrix=None): """ Encode bits using a convolutional code. Parameters ---------- message_bits : 1D ndarray containing {0, 1} Stream of bits to be convolutionally encoded. trellis: pre-initialized Trellis structure. termination: {'cont', 'term'}, optional Create ('term') or not ('cont') termination bits. puncture_matrix: 2D ndarray containing {0, 1}, optional Matrix used for the puncturing algorithm Returns ------- coded_bits : 1D ndarray containing {0, 1} Encoded bit stream. """ k = trellis.k n = trellis.n total_memory = trellis.total_memory rate = float(k)/n code_type = trellis.code_type if puncture_matrix is None: puncture_matrix = np.ones((trellis.k, trellis.n)) number_message_bits = np.size(message_bits) if termination == 'cont': inbits = message_bits number_inbits = number_message_bits number_outbits = int(number_inbits/rate) else: # Initialize an array to contain the message bits plus the truncation zeros if code_type == 'rsc': inbits = message_bits number_inbits = number_message_bits number_outbits = int((number_inbits + k * total_memory)/rate) else: number_inbits = number_message_bits + total_memory + total_memory % k inbits = np.zeros(number_inbits, 'int') # Pad the input bits with M zeros (L-th terminated truncation) inbits[0:number_message_bits] = message_bits number_outbits = int(number_inbits/rate) outbits = np.zeros(number_outbits, 'int') if puncture_matrix is not None: p_outbits = np.zeros(number_outbits, 'int') else: p_outbits = np.zeros(int(number_outbits* puncture_matrix[0:].sum()/np.size(puncture_matrix, 1)), 'int') next_state_table = trellis.next_state_table output_table = trellis.output_table # Encoding process - Each iteration of the loop represents one clock cycle current_state = 0 j = 0 for i in range(int(number_inbits/k)): # Loop through all input bits current_input = bitarray2dec(inbits[i*k:(i+1)*k]) current_output = output_table[current_state][current_input] outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 if code_type == 'rsc' and termination == 'term': term_bits = dec2bitarray(current_state, trellis.total_memory) term_bits = term_bits[::-1] for i in range(trellis.total_memory): current_input = bitarray2dec(term_bits[i*k:(i+1)*k]) current_output = output_table[current_state][current_input] outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 j = 0 for i in range(number_outbits): if puncture_matrix[0][i % np.size(puncture_matrix, 1)] == 1: p_outbits[j] = outbits[i] j = j + 1 return p_outbits
def _acs_traceback(r_codeword, trellis, decoding_type, path_metrics, paths, decoded_symbols, decoded_bits, tb_count, t, count, tb_depth, current_number_states): k = trellis.k n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs branch_metric = 0.0 next_state_table = trellis.next_state_table output_table = trellis.output_table pmetrics = np.empty(number_inputs) index_array = np.empty([number_states, 2], 'int') # Loop over all the current states (Time instant: t) for state_num in range(current_number_states): # Using the next state table find the previous states and inputs # leading into the current state (Trellis) number_found = _where_c(next_state_table, number_states, number_inputs, state_num, index_array) # Loop over all the previous states (Time instant: t-1) for i in range(number_found): previous_state = index_array[i, 0] previous_input = index_array[i, 1] # Using the output table, find the ideal codeword i_codeword = output_table[previous_state, previous_input] i_codeword_array = dec2bitarray(i_codeword, n) # Compute Branch Metrics if decoding_type == 'hard': branch_metric = hamming_dist(r_codeword.astype(int), i_codeword_array.astype(int)) elif decoding_type == 'soft': neg_LL_0 = np.log(np.exp(r_codeword) + 1) # negative log-likelihood to have received a 0 neg_LL_1 = neg_LL_0 - r_codeword # negative log-likelihood to have received a 1 branch_metric = np.where(i_codeword_array, neg_LL_1, neg_LL_0).sum() elif decoding_type == 'unquantized': i_codeword_array = 2*i_codeword_array - 1 branch_metric = euclid_dist(r_codeword, i_codeword_array) # ADD operation: Add the branch metric to the # accumulated path metric and store it in the temporary array pmetrics[i] = path_metrics[previous_state, 0] + branch_metric # COMPARE and SELECT operations # Compare and Select the minimum accumulated path metric path_metrics[state_num, 1] = pmetrics.min() # Store the previous state corresponding to the minimum # accumulated path metric min_idx = pmetrics.argmin() paths[state_num, tb_count] = index_array[min_idx, 0] # Store the previous input corresponding to the minimum # accumulated path metric decoded_symbols[state_num, tb_count] = index_array[min_idx, 1] if t >= tb_depth - 1: current_state = path_metrics[:,1].argmin() # Traceback Loop for j in reversed(range(1, tb_depth)): dec_symbol = decoded_symbols[current_state, j] previous_state = paths[current_state, j] decoded_bitarray = dec2bitarray(dec_symbol, k) decoded_bits[t - tb_depth + 1 + (j - 1) * k + count:t - tb_depth + 1 + j * k + count] = decoded_bitarray current_state = previous_state paths[:,0:tb_depth-1] = paths[:,1:] decoded_symbols[:,0:tb_depth-1] = decoded_symbols[:,1:]
import numpy as np import commpy.channelcoding.convcode as cc from commpy.utilities import dec2bitarray import binascii #*********************************************** #Conversion from text message into binary array# #*********************************************** msg = 'Hello World' #Ascci converted to hex and then to dec for s in range(len(msg)): msg_dec = int( binascii.hexlify(msg[s].encode(encoding='UTF-8', errors='strict')), 16) num = 8 * len(msg) #Convert decimal numbers into array gen = dec2bitarray(msg_dec, num) #*********************************************** # DAC parameters configuration #*********************************************** SPB = 10 #for d in range(len(gen)): # data = gen(d)*SPB print(type(gen)) print(msg) print(msg_dec) print(num) print(gen) print(len(gen)) #print(data) #++++++++++++++++++++++++++++++++++++++++++++++
def __init__(self, memory, g_matrix, feedback = None, code_type = 'default'): [self.k, self.n] = g_matrix.shape self.code_type = code_type self.total_memory = memory.sum() self.number_states = pow(2, self.total_memory) self.number_inputs = pow(2, self.k) self.next_state_table = np.zeros([self.number_states, self.number_inputs], 'int') self.output_table = np.zeros([self.number_states, self.number_inputs], 'int') if isinstance(feedback, int): warn('Trellis will only accept feedback as a matrix in the future. ' 'Using the backwards compatibility version that may contain bugs for k > 1.', DeprecationWarning) if code_type == 'rsc': for i in range(self.k): g_matrix[i][i] = feedback # Compute the entries in the next state table and the output table for current_state in range(self.number_states): for current_input in range(self.number_inputs): outbits = np.zeros(self.n, 'int') # Compute the values in the output_table for r in range(self.n): output_generator_array = np.zeros(self.k, 'int') shift_register = dec2bitarray(current_state, self.total_memory) for l in range(self.k): # Convert the number representing a polynomial into a # bit array generator_array = dec2bitarray(g_matrix[l][r], memory[l] + 1) # Loop over M delay elements of the shift register # to compute their contribution to the r-th output for i in range(memory[l]): outbits[r] = (outbits[r] + \ (shift_register[i + l] * generator_array[i + 1])) % 2 output_generator_array[l] = generator_array[0] if l == 0: feedback_array = (dec2bitarray(feedback, memory[l])[1:] * shift_register[0:memory[l]]).sum() shift_register[1:memory[l]] = \ shift_register[0:memory[l] - 1] shift_register[0] = (dec2bitarray(current_input, self.k)[0] + feedback_array) % 2 else: feedback_array = (dec2bitarray(feedback, memory[l]) * shift_register[ l + memory[l - 1] - 1:l + memory[l - 1] + memory[l] - 1]).sum() shift_register[l + memory[l - 1]:l + memory[l - 1] + memory[l] - 1] = \ shift_register[l + memory[l - 1] - 1:l + memory[l - 1] + memory[l] - 2] shift_register[l + memory[l - 1] - 1] = \ (dec2bitarray(current_input, self.k)[l] + feedback_array) % 2 # Compute the contribution of the current_input to output outbits[r] = (outbits[r] + \ (np.sum(dec2bitarray(current_input, self.k) * \ output_generator_array + feedback_array) % 2)) % 2 # Update the ouput_table using the computed output value self.output_table[current_state][current_input] = \ bitarray2dec(outbits) # Update the next_state_table using the new state of # the shift register self.next_state_table[current_state][current_input] = \ bitarray2dec(shift_register) else: if feedback is None: feedback = np.identity(self.k, int) # feedback_array[i] holds the i-th bit corresponding to each feedback polynomial. feedback_array = np.empty((self.total_memory + self.k, self.k, self.k), np.int8) for i in range(self.k): for j in range(self.k): feedback_array[:, i, j] = dec2bitarray(feedback[i, j], self.total_memory + self.k)[::-1] # g_matrix_array[i] holds the i-th bit corresponding to each g_matrix polynomial. g_matrix_array = np.empty((self.total_memory + self.k, self.k, self.n), np.int8) for i in range(self.k): for j in range(self.n): g_matrix_array[:, i, j] = dec2bitarray(g_matrix[i, j], self.total_memory + self.k)[::-1] # shift_regs holds on each column the state of a shift register. # The first row is the input of each shift reg. shift_regs = np.empty((self.total_memory + self.k, self.k), np.int8) # Compute the entries in the next state table and the output table for current_state in range(self.number_states): for current_input in range(self.number_inputs): current_state_array = dec2bitarray(current_state, self.total_memory) # Set the first row as the input. shift_regs[0] = dec2bitarray(current_input, self.k) # Set the other rows based on the current_state idx = 0 for idx_mem, mem in enumerate(memory): shift_regs[1:mem+1, idx_mem] = current_state_array[idx:idx + mem] idx += mem # Compute the output table outputs_array = np.einsum('ik,ikl->l', shift_regs, g_matrix_array) % 2 self.output_table[current_state, current_input] = bitarray2dec(outputs_array) # Update the first line based on the feedback polynomial np.einsum('ik,ilk->l', shift_regs, feedback_array, out=shift_regs[0]) shift_regs %= 2 # Update current state array and compute next state table idx = 0 for idx_mem, mem in enumerate(memory): current_state_array[idx:idx + mem] = shift_regs[:mem, idx_mem] idx += mem self.next_state_table[current_state, current_input] = bitarray2dec(current_state_array)
def test_dec2bitarray(): # Assert result assert_array_equal(dec2bitarray(17, 8), array((0, 0, 0, 1, 0, 0, 0, 1))) assert_array_equal(dec2bitarray((17, 12), 5), array((1, 0, 0, 0, 1, 0, 1, 1, 0, 0)))
def _acs_traceback(r_codeword, trellis, decoding_type, path_metrics, paths, decoded_symbols, decoded_bits, tb_count, t, count, tb_depth, current_number_states): k = trellis.k n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs branch_metric = 0.0 next_state_table = trellis.next_state_table output_table = trellis.output_table pmetrics = np.empty(number_inputs) index_array = np.empty([number_states, 2], 'int') # Loop over all the current states (Time instant: t) for state_num in range(current_number_states): # Using the next state table find the previous states and inputs # leading into the current state (Trellis) number_found = _where_c(next_state_table, number_states, number_inputs, state_num, index_array) # Loop over all the previous states (Time instant: t-1) for i in range(number_found): previous_state = index_array[i, 0] previous_input = index_array[i, 1] # Using the output table, find the ideal codeword i_codeword = output_table[previous_state, previous_input] i_codeword_array = dec2bitarray(i_codeword, n) # Compute Branch Metrics branch_metric = _compute_branch_metrics(decoding_type, tuple(r_codeword), tuple(i_codeword_array)) # ADD operation: Add the branch metric to the # accumulated path metric and store it in the temporary array pmetrics[i] = path_metrics[previous_state, 0] + branch_metric # COMPARE and SELECT operations # Compare and Select the minimum accumulated path metric path_metrics[state_num, 1] = pmetrics.min() # Store the previous state corresponding to the minimum # accumulated path metric min_idx = pmetrics.argmin() paths[state_num, tb_count] = index_array[min_idx, 0] # Store the previous input corresponding to the minimum # accumulated path metric decoded_symbols[state_num, tb_count] = index_array[min_idx, 1] if t >= tb_depth - 1: current_state = path_metrics[:, 1].argmin() # Traceback Loop for j in reversed(range(1, tb_depth)): dec_symbol = decoded_symbols[current_state, j] previous_state = paths[current_state, j] decoded_bitarray = dec2bitarray(dec_symbol, k) decoded_bits[t - tb_depth + 1 + (j - 1) * k + count:t - tb_depth + 1 + j * k + count] = decoded_bitarray current_state = previous_state paths[:, 0:tb_depth - 1] = paths[:, 1:] decoded_symbols[:, 0:tb_depth - 1] = decoded_symbols[:, 1:]
def stack_soft_decoder(receive_code, metrics, trellis): # k = trellis.k n = trellis.n # number_states = trellis.number_states number_inputs = trellis.number_inputs next_state_table = trellis.next_state_table output_table = trellis.output_table path_metric = {} r_code = convert(receive_code) list_length = 128 init_time = time.time() for i in range(10**8): # a long sequence to guarantee the iterations times of stack decoder # each receiving code to be decoded if i == 0: for j in range(number_inputs): p_metric = 0.0 output = output_table[0][j] output_array = dec2bitarray(output, n) r_code_array = array(r_code[2 * i:(2 * i + 2)]) p_metric += soft_metric( metrics, output_array[0], r_code_array[0]) + soft_metric( metrics, output_array[1], r_code_array[1]) path_metric[str(j)] = p_metric path_metric = dict( sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order from small to big elif i == 1: # get the path with best metric right now # current_best_path = dict(sorted(path_metric.items(),key = operator.itemgetter(1))[len(path_metric)-1]) last_input = list(path_metric)[len(path_metric) - 1] # last_input = max(path_metric, key=lambda k: path_metric[k]) current_state = next_state_table[0][int(last_input)] for j in range(number_inputs): p_metric = 0.0 output = output_table[current_state][j] output_array = dec2bitarray(output, n) r_code_array = array(r_code[2 * i:(2 * i + 2)]) p_metric += soft_metric( metrics, output_array[0], r_code_array[0]) + soft_metric( metrics, output_array[1], r_code_array[1]) path_metric[str(last_input) + str(j)] = path_metric[last_input] + p_metric path_metric.pop(str(last_input)) path_metric = dict( sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order as from small to big elif i >= 2: best_path_sofar = list(path_metric)[ len(path_metric) - 1] # ????it's an int other than string # best_path_sofar = max(path_metric, key=lambda k: path_metric[k]) if len(best_path_sofar) >= 2: current_state = 0 for m in best_path_sofar: # current_state = int(str(best_path_sofar)[len(best_path_sofar) - 1] + str(best_path_sofar) # [len(best_path_sofar) - 2]) current_state = next_state_table[current_state][int(m)] elif len(best_path_sofar) == 1: current_state = next_state_table[0][int(best_path_sofar)] else: current_state = 0 for j in range(number_inputs): p_metric = 0.0 output = output_table[current_state][j] output_array = dec2bitarray(output, n) r_code_array = array( r_code[2 * len(best_path_sofar):(2 * len(best_path_sofar) + 2)]) p_metric += soft_metric( metrics, output_array[0], r_code_array[0]) + soft_metric( metrics, output_array[1], r_code_array[1]) path_metric[str(best_path_sofar) + str(j)] = path_metric[best_path_sofar] + p_metric path_metric.pop(str(best_path_sofar)) path_metric = dict( sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order as from small to big if len(path_metric) > list_length: path_metric.pop(list(path_metric)[0]) if len(list(path_metric)[len(path_metric) - 1]) >= math.ceil( 0.5 * len(r_code)): break if (time.time() - init_time) > 2: break decoded_bits = max(path_metric, key=lambda k: path_metric[k]) decoded_code = [0] * len(decoded_bits) for k in range(len(decoded_bits)): decoded_code[k] = int(decoded_bits[k]) return decoded_code
def stack_decoder(receive_code, metrics, trellis, initial_state, initial_metric, discarded_path='2'): k = trellis.k n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs next_state_table = trellis.next_state_table output_table = trellis.output_table r_code = convert(receive_code) final_state = 0 path_metric = {discarded_path: -10**8} list_length = 128 M = trellis.total_memory for i in range(10**6): # a large number to guarantee the sufficient iterations times of stack decoder # each receiving code to be decoded if i == 0: for j in range(number_inputs): p_metric = 0.0 output = output_table[initial_state][j] output_array = dec2bitarray(output, n) r_code_array = array(r_code[2 * i:(2 * i + 2)]) p_metric += (soft_metric(metrics, output_array[0], r_code_array[0]) + soft_metric(metrics, output_array[1], r_code_array[1])) path_metric[str(j)] = p_metric + initial_metric path_metric = dict(sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order as from small to big elif i == 1: # get the path with best metric right now # current_best_path = dict(sorted(path_metric.items(),key = operator.itemgetter(1))[len(path_metric)-1]) # last_input = max(path_metric, key=lambda k: path_metric[k]) last_input = list(path_metric)[len(path_metric) - 1] current_state = next_state_table[initial_state][int(last_input)] for j in range(number_inputs): p_metric = 0.0 output = output_table[current_state][j] output_array = dec2bitarray(output, n) r_code_array = array(r_code[2 * i:(2 * i + 2)]) p_metric += (soft_metric(metrics, output_array[0], r_code_array[0]) + soft_metric(metrics, output_array[1], r_code_array[1])) path_metric[str(last_input) + str(j)] = path_metric[last_input] + p_metric path_metric.pop(str(last_input)) path_metric = dict(sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order as from small to big elif i >= 2: best_path_sofar = list(path_metric)[len(path_metric) - 1] # ????? it's an int other than string if len(best_path_sofar) >= 2: current_state = initial_state for m in str(best_path_sofar): # current_state = int(str(best_path_sofar)[len(best_path_sofar) - 1] + str(best_path_sofar) # [len(best_path_sofar) - 2]) current_state = next_state_table[current_state][int(m)] elif len(best_path_sofar) == 1: current_state = next_state_table[initial_state][int(best_path_sofar)] else: current_state = initial_state for j in range(number_inputs): p_metric = 0.0 output = output_table[current_state][j] output_array = dec2bitarray(output, n) r_code_array = array(r_code[2 * len(best_path_sofar):(2 * len(best_path_sofar) + 2)]) p_metric += (soft_metric(metrics, output_array[0], r_code_array[0]) + soft_metric(metrics, output_array[1], r_code_array[1])) path_metric[str(best_path_sofar) + str(j)] = path_metric[best_path_sofar] + p_metric path_metric.pop(str(best_path_sofar)) path_metric = dict(sorted(path_metric.items(), key=operator.itemgetter(1))) # dictionary always go in the order from small to big if len(path_metric) > list_length: path_metric.pop(list(path_metric)[0]) if len(list(path_metric)[len(path_metric) - 1]) >= len(r_code)*0.5: break decoded_bits = list(path_metric)[len(path_metric) - 1] ini_state_bit = list(dec2bitarray(initial_state, 8)[::-1]) final_metric = path_metric[decoded_bits] decoded_code = [0]*len(decoded_bits) for k in range(len(decoded_bits)): decoded_code[k] = int(decoded_bits[k]) # decoded_code += ini_state_bit final_state = bitarray2dec(decoded_code[(int(len(r_code) * 0.5) - M):][::-1]) return decoded_code, final_metric, final_state, decoded_bits
def polymultiply(x, y, m, prim_poly): x_array = dec2bitarray(x, m) y_array = dec2bitarray(y, m) prod = bitarray2dec(convolve(x_array, y_array) % 2) return polydivide(prod, prim_poly)
def __init__(self, memory, g_matrix, feedback=0, code_type='default'): [self.k, self.n] = g_matrix.shape if code_type == 'rsc': for i in xrange(self.k): g_matrix[i][i] = feedback self.total_memory = memory.sum() self.number_states = pow(2, self.total_memory) self.number_inputs = pow(2, self.k) self.next_state_table = np.zeros( [self.number_states, self.number_inputs], 'int') self.output_table = np.zeros([self.number_states, self.number_inputs], 'int') # Compute the entries in the next state table and the output table for current_state in xrange(self.number_states): for current_input in xrange(self.number_inputs): outbits = np.zeros(self.n, 'int') # Compute the values in the output_table for r in xrange(self.n): output_generator_array = np.zeros(self.k, 'int') shift_register = dec2bitarray(current_state, self.total_memory) for l in xrange(self.k): # Convert the number representing a polynomial into a # bit array generator_array = dec2bitarray(g_matrix[l][r], memory[l] + 1) # Loop over M delay elements of the shift register # to compute their contribution to the r-th output for i in xrange(memory[l]): outbits[r] = (outbits[r] + \ (shift_register[i+l]*generator_array[i+1])) % 2 output_generator_array[l] = generator_array[0] if l == 0: feedback_array = ( dec2bitarray(feedback, memory[l]) * shift_register[0:memory[l]]).sum() shift_register[1:memory[l]] = \ shift_register[0:memory[l]-1] shift_register[0] = (dec2bitarray( current_input, self.k)[0] + feedback_array) % 2 else: feedback_array = ( dec2bitarray(feedback, memory[l]) * shift_register[l + memory[l - 1] - 1:l + memory[l - 1] + memory[l] - 1]).sum() shift_register[l+memory[l-1]:l+memory[l-1]+memory[l]-1] = \ shift_register[l+memory[l-1]-1:l+memory[l-1]+memory[l]-2] shift_register[l+memory[l-1]-1] = \ (dec2bitarray(current_input, self.k)[l] + feedback_array) % 2 # Compute the contribution of the current_input to output outbits[r] = (outbits[r] + \ (np.sum(dec2bitarray(current_input, self.k) * \ output_generator_array + feedback_array) % 2)) % 2 # Update the ouput_table using the computed output value self.output_table[current_state][current_input] = \ bitarray2dec(outbits) # Update the next_state_table using the new state of # the shift register self.next_state_table[current_state][current_input] = \ bitarray2dec(shift_register)
def _acs_traceback(r_codeword, trellis, decoding_type, path_metrics, paths, decoded_symbols, decoded_bits, tb_count, t, count, tb_depth, current_number_states): #cdef int state_num, i, j, number_previous_states, previous_state, \ # previous_input, i_codeword, number_found, min_idx, \ # current_state, dec_symbol k = trellis.k n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs branch_metric = 0.0 next_state_table = trellis.next_state_table output_table = trellis.output_table pmetrics = np.empty(number_inputs) i_codeword_array = np.empty(n, 'int') index_array = np.empty([number_states, 2], 'int') decoded_bitarray = np.empty(k, 'int') # Loop over all the current states (Time instant: t) for state_num in range(current_number_states): # Using the next state table find the previous states and inputs # leading into the current state (Trellis) number_found = _where_c(next_state_table, number_states, number_inputs, state_num, index_array) # Loop over all the previous states (Time instant: t-1) for i in range(number_found): previous_state = index_array[i, 0] previous_input = index_array[i, 1] # Using the output table, find the ideal codeword i_codeword = output_table[previous_state, previous_input] #dec2bitarray_c(i_codeword, n, i_codeword_array) i_codeword_array = dec2bitarray(i_codeword, n) # Compute Branch Metrics if decoding_type == 'hard': #branch_metric = hamming_dist_c(r_codeword.astype(int), i_codeword_array.astype(int), n) branch_metric = hamming_dist(r_codeword.astype(int), i_codeword_array.astype(int)) elif decoding_type == 'soft': pass elif decoding_type == 'unquantized': i_codeword_array = 2*i_codeword_array - 1 branch_metric = euclid_dist(r_codeword, i_codeword_array) else: pass # ADD operation: Add the branch metric to the # accumulated path metric and store it in the temporary array pmetrics[i] = path_metrics[previous_state, 0] + branch_metric # COMPARE and SELECT operations # Compare and Select the minimum accumulated path metric path_metrics[state_num, 1] = pmetrics.min() # Store the previous state corresponding to the minimum # accumulated path metric min_idx = pmetrics.argmin() paths[state_num, tb_count] = index_array[min_idx, 0] # Store the previous input corresponding to the minimum # accumulated path metric decoded_symbols[state_num, tb_count] = index_array[min_idx, 1] if t >= tb_depth - 1: current_state = path_metrics[:,1].argmin() # Traceback Loop for j in reversed(range(1, tb_depth)): dec_symbol = decoded_symbols[current_state, j] previous_state = paths[current_state, j] decoded_bitarray = dec2bitarray(dec_symbol, k) decoded_bits[(t-tb_depth-1)+(j+1)*k+count:(t-tb_depth-1)+(j+2)*k+count] = \ decoded_bitarray current_state = previous_state paths[:,0:tb_depth-1] = paths[:,1:] decoded_symbols[:,0:tb_depth-1] = decoded_symbols[:,1:]
def _acs_traceback(r_codeword, trellis, decoding_type, path_metrics, paths, decoded_symbols, decoded_bits, tb_count, t, count, tb_depth, current_number_states): #cdef int state_num, i, j, number_previous_states, previous_state, \ # previous_input, i_codeword, number_found, min_idx, \ # current_state, dec_symbol k = trellis.k n = trellis.n number_states = trellis.number_states number_inputs = trellis.number_inputs branch_metric = 0.0 next_state_table = trellis.next_state_table output_table = trellis.output_table pmetrics = np.empty(number_inputs) i_codeword_array = np.empty(n, 'int') index_array = np.empty([number_states, 2], 'int') decoded_bitarray = np.empty(k, 'int') # Loop over all the current states (Time instant: t) for state_num in range(current_number_states): # Using the next state table find the previous states and inputs # leading into the current state (Trellis) number_found = _where_c(next_state_table, number_states, number_inputs, state_num, index_array) # Loop over all the previous states (Time instant: t-1) for i in range(number_found): previous_state = index_array[i, 0] previous_input = index_array[i, 1] # Using the output table, find the ideal codeword i_codeword = output_table[previous_state, previous_input] #dec2bitarray_c(i_codeword, n, i_codeword_array) i_codeword_array = dec2bitarray(i_codeword, n) # Compute Branch Metrics if decoding_type == 'hard': #branch_metric = hamming_dist_c(r_codeword.astype(int), i_codeword_array.astype(int), n) branch_metric = hamming_dist(r_codeword.astype(int), i_codeword_array.astype(int)) elif decoding_type == 'soft': pass elif decoding_type == 'unquantized': i_codeword_array = 2 * i_codeword_array - 1 branch_metric = euclid_dist(r_codeword, i_codeword_array) else: pass # print("branch_metric: ") # print(branch_metric) # ADD operation: Add the branch metric to the # accumulated path metric and store it in the temporary array pmetrics[i] = path_metrics[previous_state, 0] + branch_metric # COMPARE and SELECT operations # Compare and Select the minimum accumulated path metric path_metrics[state_num, 1] = pmetrics.min() # Store the previous state corresponding to the minimum # accumulated path metric min_idx = pmetrics.argmin() paths[state_num, tb_count] = index_array[min_idx, 0] # Store the previous input corresponding to the minimum # accumulated path metric decoded_symbols[state_num, tb_count] = index_array[min_idx, 1] if t >= tb_depth - 1: current_state = path_metrics[:, 1].argmin() # Traceback Loop for j in reversed(range(1, tb_depth)): dec_symbol = decoded_symbols[current_state, j] previous_state = paths[current_state, j] decoded_bitarray = dec2bitarray(dec_symbol, k) decoded_bits[(t-tb_depth-1)+(j+1)*k+count:(t-tb_depth-1)+(j+2)*k+count] = \ decoded_bitarray current_state = previous_state paths[:, 0:tb_depth - 1] = paths[:, 1:] decoded_symbols[:, 0:tb_depth - 1] = decoded_symbols[:, 1:]
def conv_encode(message_bits, trellis, code_type='default', puncture_matrix=None): """ Encode bits using a convolutional code. Parameters ---------- message_bits : 1D ndarray containing {0, 1} Stream of bits to be convolutionally encoded. generator_matrix : 2-D ndarray of ints Generator matrix G(D) of the convolutional code using which the input bits are to be encoded. M : 1D ndarray of ints Number of memory elements per input of the convolutional encoder. Returns ------- coded_bits : 1D ndarray containing {0, 1} Encoded bit stream. """ k = trellis.k n = trellis.n total_memory = trellis.total_memory rate = float(k) / n if puncture_matrix is None: puncture_matrix = np.ones((trellis.k, trellis.n)) number_message_bits = np.size(message_bits) # Initialize an array to contain the message bits plus the truncation zeros if code_type == 'default': inbits = np.zeros( number_message_bits + total_memory + total_memory % k, 'int') number_inbits = number_message_bits + total_memory + total_memory % k # Pad the input bits with M zeros (L-th terminated truncation) inbits[0:number_message_bits] = message_bits number_outbits = int(number_inbits / rate) else: inbits = message_bits number_inbits = number_message_bits number_outbits = int((number_inbits + total_memory) / rate) outbits = np.zeros(number_outbits, 'int') p_outbits = np.zeros( number_outbits * puncture_matrix[0:].sum() / np.size(puncture_matrix, 1), 'int') next_state_table = trellis.next_state_table output_table = trellis.output_table # Encoding process - Each iteration of the loop represents one clock cycle current_state = 0 j = 0 for i in xrange(number_inbits / k): # Loop through all input bits current_input = bitarray2dec(inbits[i * k:(i + 1) * k]) current_output = output_table[current_state][current_input] outbits[j * n:(j + 1) * n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 if code_type == 'rsc': term_bits = dec2bitarray(current_state, trellis.total_memory) term_bits = term_bits[::-1] for i in xrange(trellis.total_memory): current_input = bitarray2dec(term_bits[i * k:(i + 1) * k]) current_output = output_table[current_state][current_input] outbits[j * n:(j + 1) * n] = dec2bitarray(current_output, n) current_state = next_state_table[current_state][current_input] j += 1 j = 0 for i in xrange(number_outbits): if puncture_matrix[0][i % np.size(puncture_matrix, 1)] == 1: p_outbits[j] = outbits[i] j = j + 1 return p_outbits
def _identity_encode(self, data): return np.hstack([dec2bitarray(d, self.byte_width) for d in data])
def cyclic_code_genpoly(n, k): """ Generate all possible generator polynomials for a (n, k)-cyclic code. Parameters ---------- n : int Code blocklength of the cyclic code. k : int Information blocklength of the cyclic code. Returns ------- poly_list : 1D ndarray of ints A list of generator polynomials (represented as integers) for the (n, k)-cyclic code. """ if n%2 == 0: raise ValueError("n cannot be an even number") for m in arange(1, 18): if (2**m-1)%n == 0: break x_gf = GF(arange(1, 2**m), m) coset_fields = x_gf.cosets() coset_leaders = array([]) minpol_degrees = array([]) for field in coset_fields: coset_leaders = concatenate((coset_leaders, array([field.elements[0]]))) minpol_degrees = concatenate((minpol_degrees, array([len(field.elements)]))) y_gf = GF(coset_leaders, m) minpol_list = y_gf.minpolys() idx_list = arange(1, len(minpol_list)) poly_list = array([]) for i in range(1, 2**len(minpol_list)): i_array = dec2bitarray(i, len(minpol_list)) subset_array = minpol_degrees[i_array == 1] if int(subset_array.sum()) == (n-k): poly_set = minpol_list[i_array == 1] gpoly = 1 for poly in poly_set: gpoly_array = dec2bitarray(gpoly, 2**m) poly_array = dec2bitarray(poly, 2**m) gpoly = bitarray2dec(convolve(gpoly_array, poly_array) % 2) poly_list = concatenate((poly_list, array([gpoly]))) return poly_list.astype(int)