def modulate(self, input_bits): """ Modulate (map) an array of bits to constellation symbols. Parameters ---------- input_bits : 1D ndarray of ints Inputs bits to be modulated (mapped). Returns ------- baseband_symbols : 1D ndarray of complex floats Modulated complex symbols. """ index_list = map(lambda i: bitarray2dec(input_bits[i:i+self.num_bits_symbol]), \ xrange(0, len(input_bits), self.num_bits_symbol)) baseband_symbols = self.constellation[index_list] return baseband_symbols
def minpolys(self): minpol_list = array([]) full_gf = GF(arange(2**self.m), self.m) full_cosets = full_gf.cosets() for x in self.elements: for i in xrange(len(full_cosets)): if x in full_cosets[i].elements: t = array([1, full_cosets[i].elements[0]])[::-1] for root in full_cosets[i].elements[1:]: t2 = concatenate((zeros(len(t)-1), array([1, root]), zeros(len(t)-1))) prod_poly = array([]) for n in xrange(len(t2)-len(t)+1): root_sum = 0 for k in xrange(len(t)): root_sum = root_sum ^ polymultiply(int(t[k]), int(t2[n+k]), self.m, self.prim_poly) prod_poly = concatenate((prod_poly, array([root_sum]))) t = prod_poly[::-1] minpol_list = concatenate((minpol_list, array([bitarray2dec(t[::-1])]))) return minpol_list.astype(int)
def modulate(self, input_bits): """ Modulate (map) an array of bits to constellation symbols. Parameters ---------- input_bits : 1D ndarray of ints Inputs bits to be modulated (mapped). Returns ------- baseband_symbols : 1D ndarray of complex floats Modulated complex symbols. """ mapfunc = vectorize(lambda i: self.constellation[bitarray2dec(input_bits[i:i+self.num_bits_symbol])]) baseband_symbols = mapfunc(arange(0, len(input_bits), self.num_bits_symbol)) return baseband_symbols
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 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 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 __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, 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
def _identity_decode(self, data): data = np.reshape(data, (-1, self.byte_width)) return np.hstack([bitarray2dec(d) for d in data])
def databits_mapping(mapp,dbits): indices=bitarray2dec(dbits) return mapp[indices]
def databits_mapping(self): indices=bitarray2dec(self.dbits) self.symbols=self.mapp[indices]
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]) * 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 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
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)
#f_of=NDA(r_mf,M,T,H) #r_of= np.repeat(r_mf,H.shape[1]).reshape([N,RA,SA]) #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #duration test #t1=time.clock() #t=time.clock()-t1 #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #Joint Estimation for f_off,n_off and CSI n_range = N - 1 L = np.zeros(n_range - 1) #when n=0 function doesn't work,this situation should be tested by a if command for n in range(1, n_range): r = r_off_ft[:-n, :] symbs = symbols[n:] index = bitarray2dec(ibits[:, n:]) f_estt = ML_approx_unknown(r, T, symbs, ibits[:, n:]) H_est = np.zeros([RA, SA], complex) i = np.zeros(SA) #Channel estimation for k in range(0, symbs.size): H_est[:, index[k]] += r[k, :] / symbs[k] * np.exp( -1j * 2 * np.pi * T * f_estt * (k + n)) i[index[k]] = i[index[k]] + 1 #Anzahl soll auf Anzahl der Benutzung von jeder Sendeantenne angepasst werden H_est = H_est / np.repeat(i, RA).reshape(-1, RA).transpose() #Likelihood function for Timing estimation for m in range(0, symbs.size): L[n -
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)