def __init__(self, k, map_func, message): """ Constructor @param k the number of bits in each block fed into the hash function @param map_func a function that maps a 16-bit pseudo-random number into a constellation point @param message a string with the message to be transmitted """ self.k = k self.map_func = map_func # divide the mesage into blocks of k bits self.message_blocks = self._divide_message_into_blocks(message, self.k) # calculate the spine self.spine = [] spine_value = 0 for block in self.message_blocks: # Calculate the next spine value spine_value = hash_func(spine_value, block) # Add the new value to the spine self.spine.append(spine_value) # Make RNGs for each spine value self.rngs = [RNG(spine_value) for spine_value in self.spine]
def expand_wavefront_fading_P(self ,wavefront): """ Given the wavefront of the current spine location, and symbols produced from the next spine location, advance the wavefront to contain spine values from the next spine location. """ #pdb.set_trace(); k = self.k cL = len(channel) new_wavefront = [] passNum = self.passNum delay = self.delay # For each node in the current wavefront symbols, channel, PQ,head = self.para path_metric, spine_value, path, channelCache_P, channelCache_Q = wavefront fading = [] #pdb.set_trace(); # For each possible message block (2^k options) for edge in xrange( 1 << k ): # Calculate the new spine value if PQ == 0 : new_channelCache = channelCache_P[:] else: new_channelCache = channelCache_Q[:] # Get an RNG for the new spine value new_spine_value = hash_func(spine_value, edge) self.rng = RNG(new_spine_value) # Go over all received symbols, and compute the edge metric edge_metric = 0 for d in xrange(delay): node_symbolTemp = self.map_func(self.rng.next()) new_channelCache[-delay+d] = node_symbolTemp; acc = 0 for received_symbol in symbols: acc += 1 node_symbol = 0 if acc <= len(symbols)-delay: node_symbolTemp = self.map_func(self.rng.next()) new_channelCache.append(node_symbolTemp) new_channelCache = new_channelCache[1:] else: #print new_channelCache_temp new_channelCache.append(0) new_channelCache = new_channelCache[1:] #print 'node' ,new_channelCache for tt in xrange(cL): node_symbol += new_channelCache[-tt-1]*channel[tt] #print 'with fading',node_symbol distance = received_symbol - node_symbol edge_metric += distance * distance # The new path metric is the sum of all edges from the root #print 'metric', edge_metric new_path_metric = path_metric + edge_metric # Add new node to wavefront if PQ == 0 : new_wavefront = (new_path_metric, new_spine_value, path + [edge], new_channelCache,channelCache_Q) else : new_wavefront = (new_path_metric, new_spine_value, path + [edge], channelCache_P, new_channelCache) return new_wavefront
def _produce_more_values(self): ''' helper function, produces the next values to be output from the RNG, and adds them to self.next_values. This function should only be called from within the RNG class ''' from Hash import hash_func # Hash the seed with the current index hash_output = hash_func(self.seed, self.i) # Get two 16-bit words from the state self.next_values = self.next_values + [(hash_output >> 16) & 0xFFFF, hash_output & 0xFFFF] # increment current index self.i = (self.i + 3243335647) & ((1 << 32) - 1)
def _expand_wavefront(self, symbols): """ Given the wavefront of the current spine location, and symbols produced from the next spine location, advance the wavefront to contain spine values from the next spine location. """ # pdb.set_trace(); k = self.k new_wavefront = [] # For each node in the current wavefront for (path_metric, symbolsSqu, spine_value, path, waste, waste1) in self.wavefront: # For each possible message block (2^k options) for edge in xrange(1 << k): # Calculate the new spine value new_spine_value = hash_func(spine_value, edge) # Get an RNG for the new spine value rng = RNG(new_spine_value) # Go over all received symbols, and compute the edge metric edge_metric = 0 for received_symbol in symbols: # What the transmitter would have produced if it had this # spine value node_symbol = self.map_func(rng.next()) # Add the distance squared to the edge metric distance = received_symbol - node_symbol edge_metric += distance * distance # The new path metric is the sum of all edges from the root new_path_metric = path_metric + edge_metric # Add new node to wavefront new_wavefront.append( (new_path_metric, new_spine_value, path + [edge], [0])) # Update the wavefront to the newly computed wavefront self.wavefront = new_wavefront
def _expand_wavefront(self, symbols): """ Given the wavefront of the current spine location, and symbols produced from the next spine location, advance the wavefront to contain spine values from the next spine location. """ k = self.k new_wavefront = [] # For each node in the current wavefront for (path_metric, spine_value, path) in self.wavefront: # For each possible message block (2^k options) for edge in xrange(1 << k): # Calculate the new spine value new_spine_value = hash_func(spine_value, edge) # Get an RNG for the new spine value rng = RNG(new_spine_value) # Go over all received symbols, and compute the edge metric edge_metric = 0 for received_symbol in symbols: # What the transmitter would have produced if it had this spine value node_symbol = self.map_func(rng.next()) # Add the distance squared to the edge metric distance = received_symbol - node_symbol edge_metric += distance * distance # The new path metric is the sum of all edges from the root new_path_metric = path_metric + edge_metric # Add new node to wavefront new_wavefront.append( (new_path_metric, new_spine_value, path + [edge])) # Update the wavefront to the newly computed wavefront self.wavefront = new_wavefront
def _expand_wavefront_fading(self, symbols, mu): """ Given the wavefront of the current spine location, and symbols produced from the next spine location, advance the wavefront to contain spine values from the next spine location. """ k = self.k cL = len(self.channel) new_wavefront = [] passNum = self.passNum delay = self.delay # For each node in the current wavefront if len(symbols): self.receviedSymbols= self.receviedSymbols+ symbols symbolsSqu = self.receviedSymbols[:] else: symbolsSqu = [] for (path_metric, waste, spine_value, path, channelCache, waste1) in self.wavefront: # pdb.set_trace(); # For each possible message block (2^k options) for edge in xrange(1 << k): # Calculate the new spine value new_channelCache = channelCache[:] channel = self.channel[:] # Get an RNG for the new spine value new_spine_value = hash_func(spine_value, edge) self.rng = RNG(new_spine_value) # Go over all received symbols, and compute the edge metric edge_metric = 0 node_symbolTemp = 0 + 0j if len(symbols) != 0: L = min(delay, len(symbols)) for d in xrange(L): node_symbolTemp = self.map_func(self.rng.next()) new_channelCache[-delay + d] = node_symbolTemp acc = 0 for received_symbol in symbols: acc += 1 node_symbol = 0 if acc <= len(symbols) - delay: node_symbolTemp = self.map_func(self.rng.next()) new_channelCache.append(node_symbolTemp) else: new_channelCache.append(0) # print 'node' ,new_channelCache for tt in xrange(cL): if channel[tt] != 0: node_symbol += new_channelCache[-tt - 1] * channel[tt] # print 'with fading',node_symbol # pdb.set_trace() distance = received_symbol - node_symbol # if self.adaptable and acc <= len(symbols) - delay: if self.adaptable: for j in xrange(len(channel)): channel[j] = channel[j] + (mu * np.conjugate(new_channelCache[-j - 1]) * distance) # print channel edge_metric += abs(distance)**2 # pdb.set_trace() # The new path metric is the sum of all edges from the root new_path_metric = path_metric + edge_metric # print 'metric', new_path_metric # Add new node to wavefront new_wavefront.append( (new_path_metric, waste, new_spine_value, path + [edge], new_channelCache, channel)) # Update the wavefront to the newly computed wavefront self.wavefront = new_wavefront path_metric, waste, spine_value, path, channelCache, nextChannel = min(self.wavefront) self.channel = nextChannel