def __init__(self, K, glist): self.K = K # constraint length self.nstates = 2**(K-1) # number of states in state machine # number of parity bits transmitted for each message bit print glist self.r = len(glist) # States are named using (K-1)-bit integers in the range 0 to # nstates-1. The bit representation of the integer corresponds # to state label in the transition diagram. So state 10 is # named with the integer 2, state 00 is named with the # integer 0. # for each state s, figure out the two states in the diagram # that have transitions ending at state s. Record these two # states as a two-element tuple. self.predecessor_states = \ [((2*s+0) % self.nstates,(2*s+1) % self.nstates) for s in xrange(self.nstates)] # this is a 2D table implemented as a list of lists. # self.expected_parity[s1][s2] returns the r-bit sequence # of parity bits the encoder transmitted when make the # state transition from s1 to s2. self.expected_parity = \ [[PS3_tests.expected_parity(s1, s2, K, glist) \ if s1 in self.predecessor_states[s2] else None for s2 in xrange(self.nstates)] for s1 in xrange(self.nstates)]
def __init__(self, K, glist): self.K = K # constraint length self.nstates = 2**(K-1) # number of states in state machine # number of parity bits transmitted for each message bit self.r = len(glist) # States are named using (K-1)-bit integers in the range 0 to # nstates-1. The bit representation of the integer corresponds # to state label in the transition diagram. So state 10 is # named with the integer 2, state 00 is named with the # integer 0. # for each state s, figure out the two states in the diagram # that have transitions ending at state s. Record these two # states as a two-element tuple. self.predecessor_states = \ [((2*s+0) % self.nstates,(2*s+1) % self.nstates) for s in xrange(self.nstates)] # this is a 2D table implemented as a list of lists. # self.expected_parity[s1][s2] returns the r-bit sequence # of parity bits the encoder transmitted when make the # state transition from s1 to s2. self.expected_parity = \ [[PS3_tests.expected_parity(s1, s2, K, glist) \ if s1 in self.predecessor_states[s2] else None for s2 in xrange(self.nstates)] for s1 in xrange(self.nstates)]
def branch_metric(self,expected,received): hard_coded = [] for bit in received: if bit >= 0.5: new_bit = 1 else: new_bit = 0 hard_coded.append(new_bit) return PS3_tests.hamming(expected, hard_coded)
def branch_metric(self, expected, received): hard_coded = [] for bit in received: if bit >= 0.5: new_bit = 1 else: new_bit = 0 hard_coded.append(new_bit) return PS3_tests.hamming(expected, hard_coded)
def branch_metric(self, expected, received): #your code here r = len(received) digtized = [] for i in range(r): if (received[i] - THR) > -0.000000001: digtized.append(1) else: digtized.append(0) return PS3_tests.hamming(expected, digtized)
def branch_metric(self, expected, received): # your code here r = len(received) digtized = [] for i in range(r): if (received[i] - THR) > -0.000000001: digtized.append(1) else: digtized.append(0) return PS3_tests.hamming(expected, digtized)
# Note: This task will only work if the basic (hard-decision decoding) Viterbi # decoder from PS3_viterbi does. class SoftViterbiDecoder(ViterbiDecoder): # Override the default branch metric with a soft decision metric: # the square of the Euclidian distance between the # expected and received voltages. def branch_metric(self,expected,received): diff = 0 for i in xrange(len(expected)): diff += (expected[i] - received[i])**2 return diff if __name__=='__main__': # Test whether branch metrics are as expected PS3_tests.test_soft_metrics(SoftViterbiDecoder) # This test for soft decoding produces a random message of # nbits=1000 in length, from a fixed random seed (so each time the # program is run, the same behavior will occur. We encode the # message and then use your soft decoder (code above) to test it. # If the decoded stream is the same as what we expect from our # encoder, we consider the test case to have passed. Note, it is # possible (though not likely) that your soft decoder may not pass # this test case, but is in fact correct. That's why we have not # made the test case part of the verification before checkoff. K, glist = 3, (7, 5) soft = SoftViterbiDecoder(K, glist) nbits = 1000 sigma = 0.5 # noise defined as 2*sigma^2 = 1/8 numpy.random.seed(617617617)
class SoftViterbiDecoder(ViterbiDecoder): # Override the default branch metric with a soft decision metric: # the square of the Euclidian distance between the # expected and received voltages. def branch_metric(self, expected, received): #your code here bm = 0 for i in range(len(expected)): bm = bm + (expected[i] - received[i]) * (expected[i] - received[i]) return bm if __name__ == '__main__': # Test whether branch metrics are as expected PS3_tests.test_soft_metrics(SoftViterbiDecoder) # This test for soft decoding produces a random message of # nbits=1000 in length, from a fixed random seed (so each time the # program is run, the same behavior will occur. We encode the # message and then use your soft decoder (code above) to test it. # If the decoded stream is the same as what we expect from our # encoder, we consider the test case to have passed. Note, it is # possible (though not likely) that your soft decoder may not pass # this test case, but is in fact correct. That's why we have not # made the test case part of the verification before checkoff. K, glist = 3, (7, 5) soft = SoftViterbiDecoder(K, glist) nbits = 1000 sigma = 0.5 # noise defined as 2*sigma^2 = 1/8 numpy.random.seed(617617617)
# reconstruct message by tracing the most likely path # back through the matrix using self.Predecessor. return self.traceback(s,n) # print out final path metrics def dump_state(self): print self.PM[:,-1] if __name__=='__main__': constraint_len = 3; glist = (7,5,3) d = ViterbiDecoder(constraint_len, glist) # first test case: example from lecture message = [1,0,1,0,1,1,0,0] received = PS3_tests.convolutional_encoder(message, constraint_len, glist) i = 0 print 'TEST', i decoded = numpy.array(d.decode(received, debug=True)) print 'Testing without adding noise...' if (message == decoded).all() == True: print 'Successfully decoded no-noise Test 0: congratulations!' print else: print 'Oops... error in decoding no-noise Test', i print 'Decoded as ', decoded print 'Correct is', message sys.exit(1) # second batch of test cases: different constraint lengths, generators nbits = 29
def branch_metric(self,expected,received): return PS3_tests.hamming(expected, [int(round(voltage)) for voltage in received])