def single_compute(centroid, fn): map_func = lambda x: centroid[tuple(x)] mean_Es = np.average([np.sum(np.square(x)) for x in list(centroid.values())]) ber_vals = [] # EbN0 values for EbN0 in ebn0_values: # calculate N0 value to meet Eb/N0 requirement and add noise to sample EbN0_lin = 10**(0.1*EbN0) power = mean_Es/(EbN0_lin*n_bits) # Define channel channel = Channel(power) # Modulate signal mod_preamble = np.array(list(map(map_func, PREAMBLE))) mod_message = np.array(list(map(map_func, MESSAGE))) # Noisy signal mod_preamble_n = channel.AWGN(mod_preamble) mod_message_n = channel.AWGN(mod_message) # Demodulate signal demod_message = util.centroid_mapping(mod_preamble_n, PREAMBLE, mod_message_n) # Compute BER ber = np.sum(np.linalg.norm(demod_message - MESSAGE, ord=1, axis=1)) / (TEST_LEN*n_bits) # Add to list ber_vals.append(str(ber)) print(" EbN0: %8f, ber: %8f" % (EbN0, ber)) print(" done") with open(fn, "w") as f: f.write(init_string + ",".join(ber_vals) + "\n")
class System(): def __init__(self, directory, run_id, plot_every, restrict_energy, num_iterations, len_preamble, n_bits, n_hidden, stepsize, lambda_p, initial_logstd, k, noise_power): # System Parameters self.num_iterations = num_iterations self.preamble = util.generate_preamble(len_preamble, n_bits) self.restrict_energy = restrict_energy # Transmitter Parameters groundtruth = util.schemes[n_bits] t_args = [ self.preamble, restrict_energy, groundtruth, n_bits, n_hidden, lambda_p, initial_logstd ] r_args = [self.preamble, k] # Receiver Parameters self.agent_one = actor.Actor(t_args, r_args, stepsize, directory + 'agent_1/') self.agent_two = actor.Actor(t_args, r_args, stepsize, directory + 'agent_2/') # Parameters to write in the plotted diagrams p_args_names = 'run_id total_iters len_preamble stepsize lambda_p initial_logstd noise_power restrict_energy'.split( ) p_args_params = [ run_id, num_iterations, len_preamble, stepsize, lambda_p, initial_logstd, noise_power, restrict_energy ] self.p_args = dict(zip(p_args_names, p_args_params)) self.channel = Channel(noise_power) """ Action sequence that defines one full learning cycle. Starts by transmitting preamble (signal_b_1) from agent one to agent two. Agent two demodulates a guess of the preamble (signal_b_g_2) and transmits back the preamble and the generated guess of the preamble (signal_b_2, and signal_b_g_2 resp). Agent one receives these two signals and demodulates a guess of the guess of the preamble (signal_b_g_g_1) and updates its transmitter with it. """ def action_sequence(self, i): # Compute signal_b here signal_b = self.preamble # Transmit bit signal, produce modulated signal signal_m_1 = self.agent_one.transmit(signal_b) self.agent_one.save_energy(signal_m_1) # Apply channel noise, produce noisy modulated signal signal_m_1 = self.channel.AWGN(signal_m_1) # Receive mod signal, produce bit signal guess signal_b_g_2 = self.agent_two.receive(signal_m_1) # Transmit bit signal guess, # produce mod signal and mod signal guess as tuple signal_m_2 = self.agent_two.transmit(signal_b) signal_m_g_2 = self.agent_two.transmit(signal_b_g_2) # Apply channel noise, produce noisy modulated signal signal_m_2, signal_m_g_2 = self.channel.AWGN( signal_m_2), self.channel.AWGN(signal_m_g_2) # Receive mod signal guess, produce bit signal guess of guess signal_b_g_g_1 = self.agent_one.receive(signal_m_2, signal_m_g_2) # Save BER of transmitter one self.agent_one.save_ber(signal_b_g_g_1) # Update transmitter with bit signal guess of guess adv = self.agent_one.transmitter_update(signal_b_g_g_1, i) # Visualize transmitter if ((i + 1) % plot_every == 0): self.agent_one.visualize(i + 1, self.p_args) return adv """ Internal function to swap the agents for echoed learning. """ def swap_agents(self): temp = self.agent_one self.agent_one = self.agent_two self.agent_two = temp """ Run learning simulation. """ def run_sim(self, verbose): threshold = -10 # reward threshold to discard runs for i in range(self.num_iterations + 1): adv1 = self.action_sequence(i) self.swap_agents() adv2 = self.action_sequence(i) self.swap_agents() if (verbose): print("iteration %d | avg rewards: %8f %8f" % (i, adv1, adv2)) self.agent_one.save_stats() self.agent_two.save_stats() # return if the final reward is over below threshold if (adv1 < threshold or adv2 < threshold): return False return True