def test_conv_encode_viterbi_decode(self): niters = 10 blocklength = 1000 for i in range(niters): msg = randint(0, 2, blocklength) coded_bits = conv_encode(msg, self.trellis_1) decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_1, 15) assert_array_equal(decoded_bits[:-2], msg) coded_bits = conv_encode(msg, self.trellis_1) coded_syms = 2.0 * coded_bits - 1 decoded_bits = viterbi_decode(coded_syms, self.trellis_1, 15, 'unquantized') assert_array_equal(decoded_bits[:-2], msg) coded_bits = conv_encode(msg, self.trellis_2) decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_2, 15) assert_array_equal(decoded_bits[:-2], msg) coded_bits = conv_encode(msg, self.trellis_2) coded_syms = 2.0 * coded_bits - 1 decoded_bits = viterbi_decode(coded_syms, self.trellis_2, 15, 'unquantized') assert_array_equal(decoded_bits[:-2], msg)
def commpy_decode_batch(self,y): u_hat0 = cc.viterbi_decode(y[0], self.trellisNSC, self.tb_depth,'unquantized') u_hat = np.empty(shape=[y.shape[0],len(u_hat0)],dtype=np.int8) u_hat[0] = u_hat0 for i in range(len(y)-1): u_hat[i+1] = cc.viterbi_decode(y[i+1], self.trellisNSC, self.tb_depth,'unquantized') return u_hat
def test_conv_encode_viterbi_decode(self): niters = 10 blocklength = 1000 for i in xrange(niters): msg = randint(0, 2, blocklength) coded_bits = conv_encode(msg, self.trellis_1) decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_1, 15) assert_array_equal(decoded_bits[:-2], msg) coded_bits = conv_encode(msg, self.trellis_2) decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis_2, 15) assert_array_equal(decoded_bits[:-2], msg)
def decode(self, encoded: np.ndarray) -> np.ndarray: """ Use the configured trellis to perform vitirbi decoding algorithm on the received encoded bits. :param encoded: array of bits encoded then received :return: array of decoded message bits that were originally encoded (with probability varying by signal noise) """ # decode the probable bits from the encoded string decoded = cc.viterbi_decode(encoded, self._trellis, decoding_type='hard') # return the bytes from the decoded bits message = np.packbits(decoded, bitorder='big') # detect message length and truncate message_length = int.from_bytes(message[0:LENGTH_SIZE], byteorder='big', signed=False) if message_length > len(message) - LENGTH_SIZE: raise RuntimeError('Invalid message-length tag') message = message[LENGTH_SIZE:LENGTH_SIZE + message_length] logging.info( 'Decoded {} convolution coded parity bits into {}-byte message'. format(len(encoded), message_length)) return message
def conv_decoder(coded_bits): generator_matrix = np.array([[05, 07]]) M = np.array([2]) trellis = cc.Trellis(M, generator_matrix) tb_depth = 5 * (M.sum() + 1) return 2 * cc.viterbi_decode( ((coded_bits + 1) / 2).astype(float), trellis, tb_depth) - 1
def test_radio_encoder(): """Online tool to visualize Encoder: http://www.ee.unb.ca/cgi-bin/tervo/viterbi.pl """ # Create a fake packet packet = [0, 0, 1, 1] # Test convolution code encoder at different memory size EncoderTest = namedtuple('EncoderTest', ['trellis', 'wanted']) tests = [ EncoderTest( None, # default option (r= 1/2, k=3) np.array([0, 0, 0, 0, 1, 1, 0, 1])), EncoderTest(build_trellis_structure(1, 2, constraint_len=4), np.array([0, 0, 0, 0, 1, 1, 0, 1])), EncoderTest(build_trellis_structure(1, 3, constraint_len=4), np.array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0])), ] for test in tests: tx = RadioTransmitter(0, 0, 'qpsk', test.trellis) # Test correctness of encoder got, _ = tx._simulate_radio_transmitter(packet) np.testing.assert_array_equal(got, test.wanted) # Test correctness of output message by decoding with Viterbi decoded = viterbi_decode(got, tx.trellis, 4) np.testing.assert_array_equal(packet, decoded)
def turbo_compute((idx, x)): ''' Compute Turbo Decoding in 1 iterations for one SNR point. ''' np.random.seed() message_bits = np.random.randint(0, 2, args.block_len) coded_bits = cc.conv_encode(message_bits, trellis1) received = corrupt_signal(coded_bits, noise_type=args.noise_type, sigma=test_sigmas[idx], vv=args.v, radar_power=args.radar_power, radar_prob=args.radar_prob, denoise_thd=args.radar_denoise_thd) # make fair comparison between (100, 204) convolutional code and (100,200) RNN decoder, set the additional bit to 0 received[-2 * int(M):] = 0.0 decoded_bits = cc.viterbi_decode(received.astype(float), trellis1, tb_depth, decoding_type='unquantized') decoded_bits = decoded_bits[:-int(M)] num_bit_errors = hamming_dist(message_bits, decoded_bits) return num_bit_errors
def fec_decoder(self, data_in): memory = np.array([6]) g_matrix = np.array([[91, 121] ]) # G(D) = [1+D^2+D^3+D^5+D^6, 1+D+D^2+D^3+D^6] trellis = cc.Trellis(memory, g_matrix) data_out = cc.viterbi_decode(data_in, trellis, tb_depth=int(len(data_in) / 2)) return data_out[:-6]
def conv_decoder(coded_bits): generator_matrix = np.array([[05, 07]]) M = np.array([2]) trellis = cc.Trellis(M, generator_matrix) tb_depth = 5 * (M.sum() + 1) return cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth, decoding_type='unquantized')
def convdecode(self, symbols): # better do only once: self.memory = np.array([2]) self.g_matrix = np.array([[0o7, 0o5]]) self.tr = Trellis(self.memory, self.g_matrix, 0, 'default') # x = list(chr(s+ord('0')) for s in symbols) bits = np.array(x) decoded = viterbi_decode(bits, self.tr, 15) return decoded
def decoder_soft(msg): msg_d = msg puncture_matrix = Wifi80211._get_puncture_matrix(coding[0], coding[1]) if puncture_matrix: try: msg_d = cc.depuncturing(msg, puncture_matrix, math.ceil(len(msg) * coding[0] / coding[1] * 2)) except IndexError as e: print(e) print("Decoded message size %d" % (math.ceil(len(msg) * coding[0] / coding[1] * 2))) print("Encoded message size %d" % len(msg)) print("Coding %d/%d" % (coding[0], coding[1])) return cc.viterbi_decode(msg_d, trellis1, decoding_type='soft')
def test_conv_encode_viterbi_decode(self): niters = 10 blocklength = 1000 for n in range(niters): msg = randint(0, 2, blocklength) # Previous tests for i in range(len(self.trellis)): coded_bits = conv_encode(msg, self.trellis[i]) decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis[i], 15) assert_array_equal(decoded_bits[:len(msg)], msg) coded_bits = conv_encode(msg, self.trellis[i], termination='cont') decoded_bits = viterbi_decode(coded_bits.astype(float), self.trellis[i], 15) assert_array_equal(decoded_bits, msg) coded_bits = conv_encode(msg, self.trellis[i]) coded_syms = 2.0 * coded_bits - 1 decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'unquantized') assert_array_equal(decoded_bits[:len(msg)], msg) coded_bits = conv_encode(msg, self.trellis[i]) coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2 decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft') assert_array_equal(decoded_bits[:len(msg)], msg) coded_bits = conv_encode(msg, self.trellis[i], termination='cont') coded_syms = 10.0 * coded_bits - 5 + randn(len(coded_bits)) * 2 decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft') assert_array_equal(decoded_bits, msg) coded_bits = conv_encode(msg, self.trellis[i]) coded_syms = (2.0 * coded_bits - 1) * inf decoded_bits = viterbi_decode(coded_syms, self.trellis[i], 15, 'soft') assert_array_equal(decoded_bits[:len(msg)], msg) coded = conv_encode(msg, self.trellis[i], termination='cont') coded_bits = coded.astype(float) coded_bits[coded_bits == 1.0] = inf coded_bits[coded_bits == 0.0] = -inf decoded_bits = viterbi_decode(coded_bits, self.trellis[i], 15, 'soft') assert_array_equal(decoded_bits, msg)
def viterbi_decode(self, bits, signal=None): if signal is None: ht = False rate = 6 else: ht, rate, mcs = signal.ht, signal.rate, signal.mcs if (not ht and rate in [9, 18, 36, 54]) or (ht and mcs in [2, 4, 6]): print '[PUNCTURE] 3/4' # 3/4 new_bits = [] for i in range(0, len(bits), 12): new_bits.extend(bits[i:i + 3]) new_bits.extend([2, 2]) new_bits.extend(bits[i + 3:i + 7]) new_bits.extend([2, 2]) new_bits.extend(bits[i + 7:i + 11]) new_bits.extend([2, 2]) new_bits.extend(bits[i + 11:i + 12]) bits = new_bits elif (not ht and rate in [48]) or (ht and mcs in [5]): print '[PUNCTURE] 2/3' # 2/3 new_bits = [] for i in range(0, len(bits), 9): new_bits.extend(bits[i:i + 3]) new_bits.append(2) new_bits.extend(bits[i + 3:i + 6]) new_bits.append(2) new_bits.extend(bits[i + 6:i + 9]) new_bits.append(2) bits = new_bits elif ht and mcs in [7]: print '[PUNCTURE] 5/6' # 5/6 new_bits = [] for i in range(0, len(bits), 6): new_bits.extend(bits[i:i + 3]) new_bits.extend([2, 2]) new_bits.extend(bits[i + 3:i + 5]) new_bits.extend([2, 2]) new_bits.append(bits[i + 5]) bits = new_bits else: print '[NO PUNCTURE]' extended_bits = np.array([0] * 2 + bits + [0] * 12) trellis = cc.Trellis(np.array([7]), np.array([[0133, 0171]])) return list(cc.viterbi_decode(extended_bits, trellis, tb_depth=35))[:-7]
def viterbi_decode_sequences(encoded_seqs, L, rate=1 / 2): """ Given a list of convolutionally encoded sequences, uses the Viterbi algorithm on each element to decode it using a hard-decision boundary. The Trellis is generated as per the specified L and k. Returns a list of decoded elements. """ decoded_seqs = [None for _ in range(len(encoded_seqs))] generator_matrix = gen_gmatrix(L, rate) memory = np.array([L - 1]) trellis = cc.Trellis(memory, generator_matrix) for i, encoded_seq in enumerate(encoded_seqs): decoded_seq = cc.viterbi_decode(encoded_seq.astype(float), trellis) decoded_seqs[i] = decoded_seq return decoded_seqs
def conv_decoder(codeword_bits, trellis, tb_depth): return cc.viterbi_decode(codeword_bits.astype(float), trellis, tb_depth, decoding_type = 'unquantized')
if NType == 'iid': noise = test_sigmas[idx] * np.random.standard_normal( coded_bits.shape) # Define noise uu = np.sqrt(0.5) * np.random.standard_normal(coded_bits.shape) vv = np.sqrt(0.5) * np.random.standard_normal(coded_bits.shape) rayleigh_coeff = np.sqrt(uu**2 + vv**2) received = rayleigh_coeff * (2 * coded_bits - 1) + noise # Modulation plus noise # print('received: ') # print(received) decoded_bits = cc.viterbi_decode(received.astype(float), trellis, tb_depth, decoding_type='unquantized') received_odd = received[::2] # first, third, fifth, etc received_even = received[1::2] # second, fourth, sixth, etc _, map_decoded_bits = commpy.channelcoding.map_decode( sys_symbols=received_odd.astype(float), non_sys_symbols=received_even.astype(float), trellis=trellis, noise_variance=test_sigmas[idx]**2, L_int=np.zeros(received_odd.shape), mode='decode') # print('decoded_bits: ') # print(decoded_bits) num_bit_errors = hamming_dist(message_bits, decoded_bits[:-int(M)])
for trellis in (trellis1, trellis2, trellis3): for i in range(10): # Generate random message bits to be encoded message_bits = np.random.randint(0, 2, 1000) # Encode message bits coded_bits = cc.conv_encode(message_bits, trellis) # Introduce bit errors (channel) coded_bits[np.random.randint(0, 1000)] = 0 coded_bits[np.random.randint(0, 1000)] = 0 coded_bits[np.random.randint(0, 1000)] = 1 coded_bits[np.random.randint(0, 1000)] = 1 # Decode the received bits decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth) num_bit_errors = util.hamming_dist(message_bits, decoded_bits[:len(message_bits)]) if num_bit_errors != 0: print(num_bit_errors, "Bit Errors found!") elif i == 9: print("No Bit Errors :)") # ================================================================================================== # Complete example using Commpy features and compare hard and soft demodulation. Example with code 1 # ================================================================================================== # Modem : QPSK modem = mod.QAMModem(4)
# g_matrix = array([[ 109 , 79]]) # G(D) = [1+D^2, 1+D+D^2] memory = array([3]) g_matrix = array([[ 109 , 79]]) # G(D) = [1+D^2, 1+D+D^2] trellis = cc.Trellis(memory, g_matrix) # a='111101011' # message_bits = np.array(list(a)) # coded_bits = cc.conv_encode(message_bits, trellis, code_type='default', puncture_matrix=None) # print(coded_bits) bit_num = 8414 print(bit_num) num_bin = '{:016b}'.format(bit_num) num_bits = [ ] for i in num_bin: if i =='0': num_bits.append(0) elif i == '1': num_bits.append(1) num_encoded = cc.conv_encode(num_bits, trellis, code_type='default', puncture_matrix=None) print(num_encoded) # coded_bits = np.array([0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0]) # print(coded_bits) ans = cc.viterbi_decode(num_encoded, trellis, tb_depth=None, decoding_type='hard') print(ans) # print(str(message_bits)) # ans = np.array2string(np.random.randint(0,2,10000)) # ans+= '\n' # print (ans) # output_file = open("INPUT.txt", "w") # output_file.write(ans)
def decoder_hard(msg): return cc.viterbi_decode(msg, trellis1)
def commpy_decode_sequence(self,y): return cc.viterbi_decode(y, self.trellisNSC, self.tb_depth,'unquantized')
def decode(v): # demodulate and decode idx = 0 # Decode the Bit Length print('Bit Length Packet...') idx = find_header(v, idx) start_point = idx ans = [] # received bit list for i in range( 2 * (16 + memory_len) ): # 32 bit for bit_len info (add mempry_len due to conv code prop) bit = v[idx:idx + bit_len] weight0 = get_weight(signal_zero, bit) weight1 = get_weight(signal_one, bit) if weight0 >= weight1: ans.append(0) else: ans.append(1) idx += bit_len # print(ans) # decode bit length info by Veterbi Algorithm ans = np.array(ans) ans = cc.viterbi_decode(ans, trellis, tb_depth=None, decoding_type='hard')[:-memory_len] num_decoded = '' for i in range(len(ans)): if ans[i] == 1: num_decoded += '1' elif ans[i] == 0: num_decoded += '0' #Print encoded and decoded bit num # print('bit num endoded info: ', num_decoded) bit_num = int(num_decoded, 2) print('The num of bits will be received is: ', bit_num) # Decode Text Part ans = [] packet_num = 0 for j in range(bit_num): if j % packet_size == 0: # if a new packet begin idx += 3 * bit_len packet_num += 1 print('\nText info packet', packet_num) idx = find_header(v, idx) # Re-synchronize bit = v[idx:idx + bit_len] weight0 = get_weight(signal_zero, bit) weight1 = get_weight(signal_one, bit) if weight0 >= weight1: ans.append(0) else: ans.append(1) # ans.append(weight1) idx += bit_len end_point = idx # decode by Veterbi Algorithm ans = np.array(ans) ans = cc.viterbi_decode(ans, trellis, tb_depth=None, decoding_type='hard')[:-memory_len] text_decoded = '' for i in range(len(ans)): if ans[i] == 1: text_decoded += '1' elif ans[i] == 0: text_decoded += '0' if test: f = open("INPUT.txt", 'r') context = f.readlines() f.close() if (len(context) != 1): print("wrong input file") exit() text = context[0] print('\nTransimission time: ', (end_point - start_point) / sd.default.samplerate, 's') print('Receive encoded bit num: ', bit_num) print('Receive decoded bit num: ', len(text_decoded)) print('Actual send bit', len(text)) err = 0 err_list = [] for i in range(min(len(text_decoded), len(text))): if text[i] != text_decoded[i]: err += 1 err_list.append(i) print("Total error bit num : ", err) print('Acuuracy rate :', 1 - err / len(text)) print('Error list:', err_list, '\n') output_file = open("OUTPUT.txt", "w") output_file.write(text_decoded) else: output_file = open("OUTPUT.txt", "w") output_file.write(text_decoded) # ############################################ # Abandon as of now # # include repeat # else: # print('Begin to decode the first packet....') # ans_list = [] # bit_num = 0 # max_power = 0 # last_power = 0 # while True: # bit = v[idx : idx + bit_len] # power = np.dot(preamble, v[idx : idx + 5 * bit_len]) # energy = np.linalg.norm(bit) # # print (energy) # # print(power) # if power < last_power and last_power == max_power and last_power > 15*energy and power > 0 : # # print('Received bit num',bit_num-1) # ans = ans[:-1] # break # last_power = power # max_power = max(max_power,power) # weight0 = sum(signal_zero * bit) # weight1 = sum(signal_one * bit) # # print ('0 weight: ', weight0) # # print('1 weight:', weight1) # ans_list.append([weight0,weight1]) # idx += bit_len # bit_num += 1 # print('\nLooking for the scond packet...') # n = idx + 10*bit_len # power = np.dot(preamble, v[n: n + 5 * bit_len]) # # according to the device # # find the header # while power < threshold: # power = np.dot(preamble, v[n: n + 5 * bit_len]) # n += 1 # print("first step :",n) # max_power = 0 # header = n # for i in range(1, 1): # curr_power = np.dot(preamble, v[n + i: n + i + 5 * bit_len]) # if curr_power > max_power: # max_power = curr_power # header = n + i # print("second step :",header) # idx = header + bit_len * 5 # pass the preamble # print('Begin to decode the second packet....') # first_bit_num = bit_num -2 # bit_num = 0 # max_power = 0 # last_power = 0 # while True: # if bit_num > first_bit_num: # break # bit = v[idx : idx + bit_len] # power = np.dot(preamble, v[idx : idx + 5 * bit_len]) # energy = np.linalg.norm(bit) # # print (energy) # # print(power) # if power < last_power and last_power == max_power and last_power > 15*energy and power > 0 : # ans = ans[:-1] # break # last_power = power # max_power = max(max_power,power) # weight0 = sum(signal_zero * bit) # weight1 = sum(signal_one * bit) # ans_list[bit_num][0]+= weight0 # ans_list[bit_num][1]+= weight1 # idx += bit_len # bit_num += 1 # for i in range(bit_num): # if ans_list[i][0] >= ans_list[i][1]: # ans.append(0) # else: # ans.append(1) # ans = np.array(ans) # ans = cc.viterbi_decode(ans, trellis, tb_depth=None, decoding_type='hard')[:-2] # text_decoded = '' # for i in range(len(ans)): # if ans[i] == 1: # text_decoded +='1' # elif ans[i] == 0: # text_decoded +='0' # if test: # f = open("INPUT.txt", 'r') # context = f.readlines() # f.close() # if (len(context) != 1): # print("wrong input file") # exit() # text = context[0] # print(text_decoded) # print(text) # print('Receive bit num: ',bit_num) # print('Text bit num', len(text)) # err = 0 # err_list = [] # for i in range(len(text)): # if text[i] != text_decoded[i]: # err += 1 # err_list.append(i) # print("total error : ", err) # print('error rate :' , err/bit_num) # print('error list:', err_list) # else: # print('Receive bit num: ',bit_num) # print('Decode as below: ') # print(ans) # output_file = open("OUTPUT.txt", "w") # output_file.write(ans)
def decoder_soft(msg): return cc.viterbi_decode(msg, trellis1, decoding_type='soft')
# Traceback depth of the decoder tb_depth = 5*(M.sum() + 1) for i in range(10): # Generate random message bits to be encoded message_bits = np.random.randint(0, 2, 1000) # Encode message bits coded_bits = cc.conv_encode(message_bits, trellis) # Introduce bit errors (channel) #coded_bits[4] = 0 #coded_bits[7] = 0 # Decode the received bits decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth) num_bit_errors = hamming_dist(message_bits, decoded_bits[:-M]) #num_bit_errors = 1 if num_bit_errors !=0: #print(num_bit_errors, "Bit Errors found!") #print(message_bits) #print(decoded_bits[tb_depth+3:]) #print(decoded_bits) break else: print("No Bit Errors :)") #print("==== Message Bits ===") #print(message_bits)